<!DOCTYPE html>
<!-- saved from url=(0050)https://doc.kaitai.io/user_guide.html#repeat-index -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.21">
<meta name="author" content="Kaitai Project">
<title _msttexthash="27173094" _msthash="0">Kaitai Struct 用户指南</title>
<link rel="stylesheet" href="./Kaitai Struct 用户指南_files/pygments-default.css">
<link rel="stylesheet" href="./Kaitai Struct 用户指南_files/bootstrap.min.css">
<link rel="stylesheet" href="./Kaitai Struct 用户指南_files/bootstrap-theme.min.css">
<link rel="stylesheet" href="./Kaitai Struct 用户指南_files/main.css">
<link rel="stylesheet" href="./Kaitai Struct 用户指南_files/pygments-default.css">
<link rel="stylesheet" href="./Kaitai Struct 用户指南_files/colony.css">

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="" src="./Kaitai Struct 用户指南_files/analytics.js.下载"></script><script async="" src="./Kaitai Struct 用户指南_files/js"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-MFSBBRGREL');
</script>
<link rel="stylesheet" href="./Kaitai Struct 用户指南_files/asciidoctor-tabs.css">
<meta http-equiv="origin-trial" content="AymqwRC7u88Y4JPvfIF2F37QKylC04248hLCdJAsh8xgOfe/dVJPV3XS3wLFca1ZMVOtnBfVjaCMTVudWM//5g4AAAB7eyJvcmlnaW4iOiJodHRwczovL3d3dy5nb29nbGV0YWdtYW5hZ2VyLmNvbTo0NDMiLCJmZWF0dXJlIjoiUHJpdmFjeVNhbmRib3hBZHNBUElzIiwiZXhwaXJ5IjoxNjk1MTY3OTk5LCJpc1RoaXJkUGFydHkiOnRydWV9"></head>
<body class="article toc2 toc-left">
    <nav class="navbar navbar-inverse navbar-fixed-top" id="main-navbar">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-navbar-collapse" aria-expanded="false" _msthidden="1">
                    <span class="sr-only" _msttexthash="320099" _msthidden="1" _msthash="1">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <span class="navbar-brand" _msttexthash="10384452" _msthash="2">Kaitai 结构</span>
            </div>
            <div class="collapse navbar-collapse" id="main-navbar-collapse">
                <ul class="nav navbar-nav">
                    <li class=""><a href="https://kaitai.io/#what-is-it" _msttexthash="20375004" _msthash="3">这是什么？</a></li>
                    <li class=""><a href="https://kaitai.io/#quick-start" _msttexthash="11680201" _msthash="4">快速上手</a></li>
                    <li class=""><a href="https://kaitai.io/#download" _msttexthash="5638321" _msthash="5">下载</a></li>
                    <li class=""><a href="https://kaitai.io/news/" _msttexthash="6361992" _msthash="6">新闻</a></li>
                    <li class=""><a href="https://formats.kaitai.io/" _msttexthash="7791771" _msthash="7">格式库</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="https://ide.kaitai.io/" _msttexthash="12068706" _msthash="8">尝试一下 — Web IDE</a></li>
                    <li class="active"><a href="https://doc.kaitai.io/index.html" _msttexthash="5144373" _msthash="9">文档</a></li>
                </ul>
            </div>
        </div>
    </nav>
<div id="header">
<h1 _msttexthash="27173094" _msthash="10">Kaitai Struct 用户指南</h1>
<div class="details">
<font _mstmutation="1" _msttexthash="19374290" _msthash="11"><span id="author" class="author" _mstmutation="1" _istranslated="1">开泰项目</span><br _mstmutation="1" _istranslated="1"> <span id="revnumber" _mstmutation="1" _istranslated="1">0.10 版</span></font>
</div>
<div id="toc" class="toc2">
<div id="toctitle" _msttexthash="5308706" _msthash="12">目录</div>
<ul class="sectlevel1">
<li><a href="https://doc.kaitai.io/user_guide.html#_introduction" _msttexthash="7449780" _msthash="13">1. 引言</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#install-invoke" _msttexthash="21057933" _msthash="14">2. 安装和调用</a>
<ul class="sectlevel2">
<li><a href="https://doc.kaitai.io/user_guide.html#web-ide" _msttexthash="6811844" _msthash="15">2.1. Web IDE的</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#ksc" _msttexthash="35755291" _msthash="16">2.2. 桌面/控制台版本</a></li>
</ul>
</li>
<li><a href="https://doc.kaitai.io/user_guide.html#_workflow_overview" _msttexthash="25607335" _msthash="17">3. 工作流程概述</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_kaitai_struct_language" _msttexthash="33751380" _msthash="18">4. Kaitai 结构化语言</a>
<ul class="sectlevel2">
<li><a href="https://doc.kaitai.io/user_guide.html#fixed-size-struct" _msttexthash="26981630" _msthash="19">4.1. 固定尺寸结构</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#docstrings" _msttexthash="21499816" _msthash="20">4.2. 文档字符串</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#magic" _msttexthash="35514076" _msthash="21">4.3. 检查“魔术”签名</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#valid-values" _msttexthash="23741848" _msthash="22">4.4. 验证属性值</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#var-length-struct" _msttexthash="29163446" _msthash="23">4.5. 可变长度结构</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#delimited-struct" _msttexthash="19347939" _msthash="24">4.6. 分隔结构</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#enums" _msttexthash="69085315" _msthash="25">4.7. 枚举（命名整数常量）</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#types" _msttexthash="56207697" _msthash="26">4.8. 子结构（子类型）</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_accessing_attributes_in_other_types" _msttexthash="47516794" _msthash="27">4.9. 访问其他类型的属性</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_conditionals" _msttexthash="7572773" _msthash="28">4.10. 条件</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_repetitions" _msttexthash="9703590" _msthash="29">4.11. 重复</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#tlv" _msttexthash="145125981" _msthash="30">4.12. 典型的TLV实现（在表达式上切换类型）</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_instances_data_beyond_the_sequence" _msttexthash="59066514" _msthash="31">4.13. 实例：序列之外的数据</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_value_instances" _msttexthash="10902619" _msthash="32">4.14. 值实例</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_bit_sized_integers" _msttexthash="28399358" _msthash="33">4.15. 位大小的整数</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#ksy-documentation" _msttexthash="22690733" _msthash="34">4.16. 记录规范</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#meta" _msttexthash="13365105" _msthash="35">4.17. 元部分</a></li>
</ul>
</li>
<li><a href="https://doc.kaitai.io/user_guide.html#stream" _msttexthash="13801632" _msthash="36">5. 流和子流</a>
<ul class="sectlevel2">
<li><a href="https://doc.kaitai.io/user_guide.html#_limiting_total_size_of_structure" _msttexthash="40884545" _msthash="37">5.1. 限制结构的总尺寸</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#repeat-until-size-limit" _msttexthash="62208198" _msthash="38">5.2. 重复直到总大小达到限制</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_relative_positioning" _msttexthash="15707614" _msthash="39">5.3. 相对定位</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_absolute_positioning" _msttexthash="15996734" _msthash="40">5.4. 绝对定位</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_choosing_a_substream" _msttexthash="18285605" _msthash="41">5.5. 选择子流</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#process" _msttexthash="103160395" _msthash="42">5.6. 处理：处理压缩、混淆和加密的数据</a></li>
</ul>
</li>
<li><a href="https://doc.kaitai.io/user_guide.html#_expression_language" _msttexthash="19512649" _msthash="43">6. 表达语言</a>
<ul class="sectlevel2">
<li><a href="https://doc.kaitai.io/user_guide.html#_basic_data_types" _msttexthash="27259102" _msthash="44">6.1. 基本数据类型</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_composite_data_types" _msttexthash="26534144" _msthash="45">6.2. 复合数据类型</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_operators" _msttexthash="15549911" _msthash="46">6.3. 运算符</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#methods" _msttexthash="8091941" _msthash="47">6.4. 方法</a></li>
</ul>
</li>
<li><a href="https://doc.kaitai.io/user_guide.html#_advanced_techniques" _msttexthash="19968286" _msthash="48">7. 先进的技术</a>
<ul class="sectlevel2">
<li><a href="https://doc.kaitai.io/user_guide.html#switch-advanced" _msttexthash="18927285" _msthash="49">7.1. 高级切换</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#do-nothing" _msttexthash="30202835" _msthash="50">7.2. 不执行任何操作</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#delimited-struct-advanced" _msttexthash="33155707" _msthash="51">7.3. 高级分隔结构</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#meta-imports" _msttexthash="40738165" _msthash="52">7.4. 从其他文件导入类型</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#opaque-types" _msttexthash="76902033" _msthash="53">7.5. 不透明类型：插入外部代码</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#custom-process" _msttexthash="32902623" _msthash="54">7.6. 自定义处理例程</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_enforcing_parent_type" _msttexthash="34681634" _msthash="55">7.7. 强制执行父类型</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#typecast" _msttexthash="18910866" _msthash="56">7.8. 类型转换</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#calc-endian" _msttexthash="40306721" _msthash="57">7.9. 计算默认字节序</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#param-types" _msttexthash="17931823" _msthash="58">7.10. 参数类型</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#repeat-index" _msttexthash="19381505" _msthash="59">7.11. 重复指数</a></li>
</ul>
</li>
<li><a href="https://doc.kaitai.io/user_guide.html#_common_pitfalls" _msttexthash="18922631" _msthash="60">8. 常见陷阱</a>
<ul class="sectlevel2">
<li><a href="https://doc.kaitai.io/user_guide.html#_specifying_size_creates_a_substream" _msttexthash="52473642" _msthash="61">8.1. 指定大小会创建一个子流</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_not_specifying_size_does_not_create_a_substream" _msttexthash="53734096" _msthash="62">8.2. 未指定大小不会创建子流</a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#_applying_process_without_a_size" _msttexthash="50298911" _msthash="63">8.3. 没有尺寸的应用<code _istranslated="1">过程</code></a></li>
<li><a href="https://doc.kaitai.io/user_guide.html#keys-repeated" _msttexthash="130987753" _msthash="64">8.4. 与整个数组和重复属性中每个元素相关的键</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="_introduction" _msttexthash="7449780" _msthash="65">1. 引言</h2>
<div class="sectionbody">
<div class="paragraph">
<p _msttexthash="555925409" _msthash="66">Kaitai Struct 是一种特定于领域的语言 （DSL），旨在
牢记一项特定任务：处理任意二进制文件
格式。</p>
</div>
<div class="paragraph">
<p _msttexthash="3367786383" _msthash="67">解析二进制格式很困难，这是有原因的：这样
格式被设计为机器可读，而不是人类可读。甚至
当一个人使用干净的、有据可查的格式时，有
等待开发人员的多个陷阱：字节序问题，
内存中结构对齐、可变大小结构、条件
字段、重复项、以前依赖其他字段的字段
阅读，等等，等等，仅举几例。</p>
</div>
<div class="paragraph">
<p _msttexthash="889199337" _msthash="68">Kaitai Struct 试图将开发人员与所有这些细节隔离开来
并允许他们专注于重要的事情：数据结构
本身，而不是读取或写入它的特定方式。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="install-invoke" _msttexthash="21057933" _msthash="69">2. 安装和调用</h2>
<div class="sectionbody">
<div class="paragraph">
<p _msttexthash="260915733" _msthash="70">Kaitai Struct 有一个多样化的基础设施。这
本章将概述可用的选项。</p>
</div>
<div class="sect2">
<h3 id="web-ide" _msttexthash="6811844" _msthash="71">2.1. Web IDE的</h3>
<div class="paragraph">
<p _msttexthash="622969659" _msthash="72">如果您是第一次尝试 Kaitai Struct，
Web IDE 可能是最简单的入门方法。只需打开 <a href="https://ide.kaitai.io/" _istranslated="1">Kaitai Struct Web IDE</a>，您就可以了
准备就绪：</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./Kaitai Struct 用户指南_files/webide_png_example.png" alt="Kaitai Struct Web IDE（示例 PNG 文件 + png.ksy 已加载）" width="1335" height="811" _mstalt="1734967" _msthash="73">
</div>
<div class="title" _msttexthash="147291937" _msthash="74">图 1：Kaitai Struct Web IDE（示例 PNG 文件 + png.ksy 加载）</div>
</div>
<div class="paragraph">
<p _msttexthash="83707884" _msthash="75">Web IDE 功能列表可在 <a href="https://github.com/kaitai-io/kaitai_struct_webide/wiki/Features" _istranslated="1"><em _istranslated="1">kaitai_struct_webide</em> GitHub wiki</a> 上找到。</p>
</div>
<div class="paragraph">
<p _msttexthash="91052286" _msthash="76">请注意，Web IDE 有两个不同的版本：</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p _msttexthash="421753514" _msthash="77"><a href="https://ide.kaitai.io/" class="bare" _istranslated="1">https://ide.kaitai.io/</a> — <strong _istranslated="1">稳定</strong>版，有稳定的 Kaitai Struct
编译器（当前 0.10，发布于 2022-07-08）</p>
</li>
<li>
<p _msttexthash="451757462" _msthash="78"><a href="https://ide.kaitai.io/devel/" class="bare" _istranslated="1">https://ide.kaitai.io/devel/</a> — 不稳定的开发版本，具有<strong _istranslated="1">最新的</strong>编译器（最新的 0.11-SNAPSHOT）</p>
</li>
</ol>
</div>
<div class="paragraph">
<p _msttexthash="85178717" _msthash="79">如果要使用最新功能，请使用<a href="https://ide.kaitai.io/devel/" _istranslated="1"><strong _istranslated="1">开发</strong> Web IDE</a>。</p>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="80">注意</div>
</td>
<td class="content" _msttexthash="480541516" _msthash="81"><a href="https://ide.kaitai.io/devel/" _istranslated="1"><strong _istranslated="1">devel</strong> Web IDE</a> 遵循 <a href="https://github.com/kaitai-io/kaitai_struct_webide" _istranslated="1">kaitai_struct_webide</a> 存储库的默认 <a href="https://github.com/kaitai-io/kaitai_struct_webide/tree/master" _istranslated="1"><code _istranslated="1">master</code> 分支</a> — 当 <a href="https://github.com/kaitai-io/kaitai_struct_webide/tree/master" _istranslated="1"><code _istranslated="1">master</code> 分支</a>更新时，它会自动更新。</td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="ksc" _msttexthash="35755291" _msthash="82">2.2. 桌面/控制台版本</h3>
<div class="paragraph">
<p _msttexthash="1184202448" _msthash="83">如果您不喜欢在浏览器中使用十六进制转储，或者想将 Kaitai Struct 集成到您的项目构建中
流程自动化，您需要一个桌面/控制台解决方案。之
当然，Kaitai Struct 也提供了这一点。</p>
</div>
<div class="sect3">
<h4 id="ksc-install" _msttexthash="10367890" _msthash="84">2.2.1. 安装</h4>
<div class="paragraph">
<p _msttexthash="147944225" _msthash="85">请参考<a href="https://kaitai.io/#download" _istranslated="1">官方网站</a>
安装说明。安装后，您将拥有：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>ksc</code><font _mstmutation="1" _msttexthash="353452099" _msthash="86">（或 ） — 命令行 Kaitai Struct
编译器，一个转换为解析库的程序
选定的目标语言。</font><code>kaitai-struct-compiler</code><code>.ksy</code></p>
</li>
<li>
<p><code>ksv</code><font _mstmutation="1" _msttexthash="79245881" _msthash="87">（或 ， 可选） — 控制台可视化工具</font><code>kaitai-struct-visualizer</code></p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="88">注意</div>
</td>
<td class="content">
<code>ksc</code><font _mstmutation="1" _msttexthash="484218644" _msthash="89">或者，如果您的系统不提供速记，则速记可能不可用
支持符号链接 — 在这种情况下，只需使用全名即可。</font><code>ksv</code></td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2566375721" _msthash="90">如果你要频繁调用，你可能想要添加
它添加到您的可执行文件搜索中，因此您不必键入完整的
每次都通往它的路径。你会自动.deb包裹上得到它
和 Windows .msi安装（前提是您不禁用该选项）-
但是，如果您使用通用.zip，则可能需要一些额外的手动设置
包。</font><code>ksc</code><code>PATH</code></p>
</div>
</div>
<div class="sect3">
<h4 id="invocation" _msttexthash="11551501" _msthash="91">2.2.2. 调用</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="26590668" _msthash="92">调用很简单：</font><code>ksc</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="shell"><span></span>ksc<span class="tok-w"> </span><span class="tok-o">[</span>options<span class="tok-o">]</span><span class="tok-w"> </span>&lt;file&gt;...</code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="24041277" _msthash="93">常用选项：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>&lt;file&gt;…​</code><font _mstmutation="1" _msttexthash="32345755" _msthash="94">— 源文件 （.ksy）</font></p>
</li>
<li>
<p><code>-t &lt;language&gt; | --target &lt;language&gt;</code><font _mstmutation="1" _msttexthash="121988217" _msthash="95">— 目标语言 （， ， ， ， ， ， ，</font><code>cpp_stl</code><code>csharp</code><code>java</code><code>javascript</code><code>perl</code><code>php</code><code>python</code><code>ruby</code><code>all</code>)</p>
<div class="ulist">
<ul>
<li>
<p><code>all</code><font _mstmutation="1" _msttexthash="869873901" _msthash="96">是一个特例：它编译了所有可能的目标
语言，创建特定于语言的目录（根据语言
标识符），然后创建输出
从那里开始的每种语言的模块</font></p>
</li>
</ul>
</div>
</li>
<li>
<p><code>-d &lt;directory&gt; | --outdir &lt;directory&gt;</code><font _mstmutation="1" _msttexthash="85883499" _msthash="97">— 输出目录
（文件名将自动生成）</font></p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="47970312" _msthash="98">特定于语言的选项：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>--dotnet-namespace &lt;namespace&gt;</code><font _mstmutation="1" _msttexthash="135095077" _msthash="99">— .NET 命名空间（仅限 C#，默认：Kaitai）</font></p>
</li>
<li>
<p><code>--java-package &lt;package&gt;</code><font _mstmutation="1" _msttexthash="116734254" _msthash="100">— Java 包（仅限 Java，默认：root 包）</font></p>
</li>
<li>
<p><code>--php-namespace &lt;namespace&gt;</code><font _mstmutation="1" _msttexthash="139145929" _msthash="101">— PHP 命名空间（仅限 PHP，默认：root 包）</font></p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="22723831" _msthash="102">其他选项：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>--verbose</code><font _mstmutation="1" _msttexthash="16048214" _msthash="103">— 详细输出</font></p>
</li>
<li>
<p><code>--help</code><font _mstmutation="1" _msttexthash="37351691" _msthash="104">— 显示使用信息并退出</font></p>
</li>
<li>
<p><code>--version</code><font _mstmutation="1" _msttexthash="37997401" _msthash="105">— 显示版本信息并退出</font></p>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_workflow_overview" _msttexthash="25607335" _msthash="106">3. 工作流程概述</h2>
<div class="sectionbody">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1063388053" _msthash="107">Kaitai Struct 的主要思想是创建二进制数据的描述
使用形式化语言进行结构格式化，将其另存为文件，以及
然后用Kaitai Struct编译器编译成目标编程语言。</font><code>.ksy</code></p>
</div>
<div class="paragraph">
<p _msttexthash="11851632" _msthash="108">待办事项</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_kaitai_struct_language" _msttexthash="33751380" _msthash="109">4. Kaitai 结构化语言</h2>
<div class="sectionbody">
<div class="paragraph">
<p _msttexthash="199245527" _msthash="110">解决了工作流程问题后，让我们专注于开泰
结构化语言本身。</p>
</div>
<div class="sect2">
<h3 id="fixed-size-struct" _msttexthash="26981630" _msthash="111">4.1. 固定尺寸结构</h3>
<div class="paragraph">
<p _msttexthash="1146749188" _msthash="112">Kaitai Struct 能做的最简单的事情可能是读取固定大小的结构。
您可能将它们称为 C 结构定义——考虑类似
这个虚构的数据库条目，用于跟踪狗表演
参与者：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c"><span></span><span class="tok-k">struct</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-kt">char</span><span class="tok-w"> </span><span class="tok-n">uuid</span><span class="tok-p">[</span><span class="tok-mi">16</span><span class="tok-p">];</span><span class="tok-w">       </span><span class="tok-cm">/* 128-bit UUID */</span>
<span class="tok-w">    </span><span class="tok-kt">char</span><span class="tok-w"> </span><span class="tok-n">name</span><span class="tok-p">[</span><span class="tok-mi">24</span><span class="tok-p">];</span><span class="tok-w">       </span><span class="tok-cm">/* Name of the animal */</span>
<span class="tok-w">    </span><span class="tok-kt">uint16_t</span><span class="tok-w"> </span><span class="tok-n">birth_year</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-cm">/* Year of birth, used to calculate the age */</span>
<span class="tok-w">    </span><span class="tok-kt">double</span><span class="tok-w"> </span><span class="tok-n">weight</span><span class="tok-p">;</span><span class="tok-w">       </span><span class="tok-cm">/* Current weight in kg */</span>
<span class="tok-w">    </span><span class="tok-kt">int32_t</span><span class="tok-w"> </span><span class="tok-n">rating</span><span class="tok-p">;</span><span class="tok-w">      </span><span class="tok-cm">/* Rating, can be negative */</span>
<span class="tok-p">}</span><span class="tok-w"> </span><span class="tok-n">animal_record</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="53146418" _msthash="113">以下是它在 .ksy 中的样子：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">animal_record</span>
<span class="tok-w">  </span><span class="tok-nt">endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">be</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">uuid</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">16</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">24</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">birth_year</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">weight</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">f8</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rating</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">s4</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1283728992" _msthash="114">它是一种基于 <a href="https://learnxinyminutes.com/docs/yaml/" _mstmutation="1" _istranslated="1">YAML</a> 的格式，
简单明了。每个 .ksy 文件都是一个类型描述。万事
从一个部分开始：这是我们指定顶级信息的地方
我们描述的整个结构。这里有两件重要的事情：</font><code>meta</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>id</code><font _mstmutation="1" _msttexthash="24960156" _msthash="115">指定结构的名称</font></p>
</li>
<li>
<p><code>endian</code><font _mstmutation="1" _msttexthash="38683073" _msthash="116">指定默认<a href="https://en.wikipedia.org/wiki/Endianness" _mstmutation="1" _istranslated="1">字节序</a>：</font></p>
<div class="ulist">
<ul>
<li>
<p><code>be</code><font _mstmutation="1" _msttexthash="179757851" _msthash="117">对于大端（又名“网络字节顺序”，又名摩托罗拉等）</font></p>
</li>
<li>
<p><code>le</code><font _mstmutation="1" _msttexthash="88888410" _msthash="118">对于 little-endian（又名 Intel、AKA VAX 等）</font></p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="685261902" _msthash="119">这样一来，我们使用一个带有数组的元素（有序的
元素序列）来描述此结构的属性
由组成。每个属性都包含多个键，即：</font><code>seq</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>id</code><font _mstmutation="1" _msttexthash="20768176" _msthash="120">用于为属性命名</font></p>
</li>
<li>
<p><code>type</code><font _mstmutation="1" _msttexthash="29802084" _msthash="121">指定属性类型：</font></p>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="247340886" _msthash="122">没有类型意味着我们只处理一个原始字节数组; 用于指定此数组中的字节数</font><code>size</code></p>
</li>
<li>
<p><code>s1</code><font _mstmutation="1" _msttexthash="34128133" _msthash="123">、 、 、 、 、 等 表示 整数</font><code>s2</code><code>s4</code><code>u1</code><code>u2</code><code>u4</code></p>
<div class="ulist">
<ul>
<li>
<p _msttexthash="79702727" _msthash="124">“s”表示有符号，“u”表示无符号</p>
</li>
<li>
<p _msttexthash="20672769" _msthash="125">number 是字节数</p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="174614011" _msthash="126">如果需要指定非默认字节序，可以强制指定
追加 或 — 即 、 等</font><code>be</code><code>le</code><code>s4be</code><code>u8le</code></p>
</li>
</ul>
</div>
</li>
<li>
<p><code>f4</code><font _mstmutation="1" _msttexthash="239108753" _msthash="127">以及 IEEE 754 浮点数; 和
同样，指定字节数（单精度或双精度）</font><code>f8</code><code>4</code><code>8</code></p>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="174614011" _msthash="128">如果需要指定非默认字节序，可以强制指定
追加 或 — 即 、 等</font><code>be</code><code>le</code><code>f4be</code><code>f8le</code></p>
</li>
</ul>
</div>
</li>
<li>
<p><code>str</code><font _mstmutation="1" _msttexthash="292738160" _msthash="129">用于字符串;这与“无类型”几乎相同，但
字符串具有编码的概念，必须使用</font><code>encoding</code></p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="1329407742" _msthash="130">基于 YAML 的语法可能看起来比类似 C 的结构更冗长一些，
但是使用它有几个很好的理由。它是一致的，它是
易于扩展，易于解析，因此很容易制作自己的
使用 .ksy 规范的程序/脚本。</p>
</div>
</div>
<div class="sect2">
<h3 id="docstrings" _msttexthash="21499816" _msthash="131">4.2. 文档字符串</h3>
<div class="paragraph">
<p _msttexthash="347791132" _msthash="132">一个非常简单的例子是，我们可以向每个属性添加文档字符串，
使用这样的语法：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rating</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">s4</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Rating, can be negative</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="3361377370" _msthash="133">这些文档字符串不仅仅是 .ksy 文件中的注释，它们实际上会得到
也可以导出为目标语言（例如，在 Java 中，它们将
成为 JavaDoc，在 Ruby 中它们将成为 RDoc/YARD 等）。这反过来又是
在各种 IDE 中编辑代码时非常有用，这些代码将
生成提醒弹出窗口，以便在您浏览时智能完成
通过类属性：</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./Kaitai Struct 用户指南_files/completion_javadoc.png" alt="JavaDoc 是从 &#39;doc&#39; 自动生成的" width="1188" height="366" _mstalt="1449578" _msthash="134">
</div>
<div class="title"><font _mstmutation="1" _msttexthash="90767625" _msthash="135">图 2：JavaDoc 是从以下位置自动生成的</font><code>doc</code></div>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="136">注意</div>
</td>
<td class="content">
<div class="paragraph">
<p _msttexthash="217230481" _msthash="137">您可以使用 YAML
折叠样式字符串，用于跨多行的较长文档：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">opcode</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">|</span>
<span class="tok-w">      </span><span class="tok-no">Operation code that defines which operation should be performed</span>
<span class="tok-w">      </span><span class="tok-no">by a virtual machine. Subsequent parameters for operation depend</span>
<span class="tok-w">      </span><span class="tok-no">on the value of opcode.</span></code></pre>
</div>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="magic" _msttexthash="35514076" _msthash="138">4.3. 检查“魔术”签名</h3>
<div class="paragraph">
<p _msttexthash="2537111174" _msthash="139">许多文件格式使用某种保护措施来防止使用
完全不同的文件类型代替所需的文件类型。这
这样做的简单方法是包含一些“魔术”字节（又名“文件”
signature“）：例如，检查文件的第一个字节是否等于
它们的预期值至少提供了一定程度的保护
反对这样的错误。</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="595243974" _msthash="140">为了在结构中指定“魔术”字节（即固定内容），Kaitai Struct 包括
一把特殊的钥匙。例如，这是 Java .class 文件的开头：</font><code>contents</code><code>seq</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic</span>
<span class="tok-w">    </span><span class="tok-nt">contents</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">[</span><span class="tok-nv">0xca</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">0xfe</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">0xba</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">0xbe</span><span class="tok-p tok-p-Indicator">]</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2041310245" _msthash="141">这将读取前 4 个字节并将它们与 4 个字节进行比较。如果
存在任何不匹配（或读取的字节少于 4 个字节），
它会抛出一个异常，并在早期阶段停止解析，然后再进行任何
损坏（无意义地分配巨大的结构，浪费CPU周期）
完成。</font><code>CA FE BA BE</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="123103773" _msthash="142">请注意，这是非常灵活的，您可以指定：</font><code>contents</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="117070148" _msthash="143">UTF-8 字符串 — 将检查来自此类字符串的字节</p>
</li>
<li>
<p _msttexthash="48780680" _msthash="144">一个数组，其中包含：</p>
<div class="ulist">
<ul>
<li>
<p _msttexthash="36229479" _msthash="145">十进制表示中的字节</p>
</li>
<li>
<p _msttexthash="81801863" _msthash="146">十六进制表示形式的字节，以 0x 开头</p>
</li>
<li>
<p _msttexthash="12657437" _msthash="147">UTF-8 字符串</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="347545445" _msthash="148">在使用数组的情况下，所有元素的字节表示形式都是
按顺序连接和预期。一些例子：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic1</span>
<span class="tok-w">    </span><span class="tok-nt">contents</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">JFIF</span>
<span class="tok-w">    </span><span class="tok-c1"># expects bytes: 4A 46 49 46</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic2</span>
<span class="tok-w">    </span><span class="tok-c1"># we can use YAML block-style arrays as well</span>
<span class="tok-w">    </span><span class="tok-nt">contents</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0xca</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0xfe</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0xba</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0xbe</span>
<span class="tok-w">    </span><span class="tok-c1"># expects bytes: CA FE BA BE</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic3</span>
<span class="tok-w">    </span><span class="tok-nt">contents</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">[</span><span class="tok-nv">CAFE</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">0</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">BABE</span><span class="tok-p tok-p-Indicator">]</span>
<span class="tok-w">    </span><span class="tok-c1"># expects bytes: 43 41 46 45 00 42 41 42 45</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="356252260" _msthash="149">更极端的例子来说明这个想法（即可能，但
绝对不推荐在现实生活中的规格）：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic4</span>
<span class="tok-w">    </span><span class="tok-nt">contents</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">[</span><span class="tok-nv">foo</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">0</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">A</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">0xa</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">42</span><span class="tok-p tok-p-Indicator">]</span>
<span class="tok-w">    </span><span class="tok-c1"># expects bytes: 66 6F 6F 00 41 0A 2A</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic5</span>
<span class="tok-w">    </span><span class="tok-nt">contents</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">[</span><span class="tok-nv">1</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">0x55</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-s">'▒,3'</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">3</span><span class="tok-p tok-p-Indicator">]</span>
<span class="tok-w">    </span><span class="tok-c1"># expects bytes: 01 55 E2 96 92 2C 33 03</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="150">注意</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="144857414" _msthash="151">无需指定或固定内容
数据 — 这一切都自然而然地来自 .</font><code>type</code><code>size</code><code>contents</code></td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="valid-values" _msttexthash="23741848" _msthash="152">4.4. 验证属性值</h3>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="7057479" _msthash="153">重要</div>
</td>
<td class="content" _msttexthash="39918580" _msthash="154">从 v0.9 开始提供的功能。</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1291213924" _msthash="155">确保数据结构中的属性符合预期格式
和范围，Kaitai Struct 提供了一种验证属性的机制
值。此键允许您定义约束
对于值，增强规格的稳健性。方法如下
您可以强制实施以下约束：</font><code>valid</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>eq</code><font _mstmutation="1" _msttexthash="144137279" _msthash="156">（或直接）：确保属性值准确无误
匹配给定的值。</font><code>valid: value</code></p>
</li>
<li>
<p><code>min</code><font _mstmutation="1" _msttexthash="49347090" _msthash="157">：指定属性的最小有效值。</font></p>
</li>
<li>
<p><code>max</code><font _mstmutation="1" _msttexthash="49211682" _msthash="158">：指定属性的最大有效值。</font></p>
</li>
<li>
<p><code>any-of</code><font _mstmutation="1" _msttexthash="134966299" _msthash="159">：定义可接受值的列表，其中一个
属性必须匹配。</font></p>
</li>
<li>
<p><code>expr</code><font _mstmutation="1" _msttexthash="170472367" _msthash="160">：计算结果为 true 的表达式，属性为
被认为是有效的。</font></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="238620928" _msthash="161">在大多数情况下，直接快捷方式因其简单性而首选，可以有效地用作 .</font><code>valid: value</code><code>valid/eq</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-c1"># Full form of equality constraint: the only valid value is 0x42</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">exact_value1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">valid</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">eq</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x42</span>

<span class="tok-w">  </span><span class="tok-c1"># Shortcut for the above: the only valid value is 0x42</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">exact_value2</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">valid</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x42</span>

<span class="tok-w">  </span><span class="tok-c1"># Value must be at least 100 and at most 200</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">bounded_value</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2</span>
<span class="tok-w">    </span><span class="tok-nt">valid</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">min</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">100</span>
<span class="tok-w">      </span><span class="tok-nt">max</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">200</span>

<span class="tok-w">  </span><span class="tok-c1"># Value must be one of 3, 5, or 7</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">enum_constraint_value</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">valid</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">any-of</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">[</span><span class="tok-nv">3</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">5</span><span class="tok-p tok-p-Indicator">,</span><span class="tok-w"> </span><span class="tok-nv">7</span><span class="tok-p tok-p-Indicator">]</span>

<span class="tok-w">  </span><span class="tok-c1"># Value must be even</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr_constraint_value</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">valid</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_ % 2 == 0</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="1179315228" _msthash="162">当一个值不满足指定的条件时，Kaitai Struct 会引发一个
验证错误，停止进一步解析。这种先发制人的措施
确保正在解析的数据在预期域内，提供
第一层错误处理。</p>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="163">注意</div>
</td>
<td class="content" _msttexthash="401449490" _msthash="164">验证检查的实际实现是
取决于语言，并且可能在行为和支持的功能上有所不同
不同的目标语言。</td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="var-length-struct" _msttexthash="29163446" _msthash="165">4.5. 可变长度结构</h3>
<div class="paragraph">
<p _msttexthash="902549089" _msthash="166">许多协议和文件格式倾向于节省字节，尤其是
字符串。当然，为字符串设置固定的 512 字节缓冲区是愚蠢的
通常为 3-5 个字节，极少数可以达到 512 个字节。</p>
</div>
<div class="paragraph">
<p _msttexthash="1965103244" _msthash="167">用于缓解此问题的最常见方法之一是使用
一些整数来指定字符串的长度，并且仅存储
流中指定的字节数。不幸的是，这会产生
一个可变长度的结构，不可能描述这样的事情
使用 C 样式结构。但是，这对 Kaitai Struct 来说不是问题：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_str</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_len</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2689802635" _msthash="168">注意字段：我们使用的不是常量，而是对字段的引用
我们刚刚从流中解析出来。实际上，您可以做得更多
除此之外，您还可以在现场使用成熟的表达式语言。例如，如果我们处理的是 UTF-16 字符串，并且 value 指定的不是字节数，而是字节数，该怎么办？
对？</font><code>size</code><code>size</code><code>my_len</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_str</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_len * 2</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-16LE</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="504872056" _msthash="169">一个人可以乘以 2——瞧——这就是我们的 UTF-16
字符串。表达语言非常强大，我们将更多地讨论
稍后再说。</font><code>my_len</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="607685338" _msthash="170">最后但并非最不重要的一点是，我们可以指定一个自动跨越到
流的尽头。对于这一点，我们将使用略有不同的
语法：</font><code>size</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">some_int</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">string_spanning_to_the_end_of_file</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span>
<span class="tok-w">    </span><span class="tok-nt">size-eos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">true</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="delimited-struct" _msttexthash="19347939" _msthash="171">4.6. 分隔结构</h3>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="172">注意</div>
</td>
<td class="content" _msttexthash="291884307" _msthash="173">本节中指定的所有功能都在
字符串，但相同的功能也应该适用于任何用户类型。</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="942757855" _msthash="174">避免分配大量固定大小缓冲区的另一种流行方法是
使用某种尾随分隔符。最著名的例子
这可能是以 null 结尾的字符串，它成为了标准
C 中的字符串表示：</p>
</div>
<div class="literalblock">
<div class="content">
<pre>61 62 63 00</pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="2490392645" _msthash="175">这 4 个字节实际上代表 3 个字符的字符串“abc”，外加一个额外的
尾随字节“0”（又名 null），用作分隔符或
终结者。根据协议，C 字符串不能包含零字节：每次
C 中的函数看到，无论是在流中还是在内存中，它都认为
作为停止处理的特殊标记。</p>
</div>
<div class="paragraph">
<p _msttexthash="409874790" _msthash="176">在 Kaitai Struct 中，您可以定义各种分隔符
结构。例如，这是定义以 null 结尾的
字符串：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_string</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="227144463" _msthash="177">由于这是一件很常见的事情，因此有一个快捷方式 和 .可以这样写：</font><code>type: str</code><code>terminator: 0</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_string</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="687711466" _msthash="178">当然，您可以使用任何其他字节（例如，AKA
换行符）作为终结符。这给 Kaitai Struct 带来了一些局限性
还能够解析某些文本格式。</font><code>0xa</code></p>
</div>
<div class="paragraph">
<p _msttexthash="316823871" _msthash="179">读取“直到遇到终止符字节”可能是
危险。如果我们从未遇到过那个字节怎么办？</p>
</div>
<div class="paragraph">
<p _msttexthash="827717995" _msthash="180">另一个非常普遍的模型实际上<strong _istranslated="1">具有</strong>固定大小的
字符串<strong _istranslated="1">和</strong>终止符的缓冲区。这通常是一个项目
从 C 序列化这样的结构。例如，以这个为例
结构：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c"><span></span><span class="tok-k">struct</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-kt">char</span><span class="tok-w"> </span><span class="tok-n">name</span><span class="tok-p">[</span><span class="tok-mi">16</span><span class="tok-p">];</span><span class="tok-w">       </span><span class="tok-cm">/* Name of the animal */</span>
<span class="tok-w">    </span><span class="tok-kt">uint16_t</span><span class="tok-w"> </span><span class="tok-n">birth_year</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-cm">/* Year of birth, used to calculate the age */</span>
<span class="tok-p">}</span><span class="tok-w"> </span><span class="tok-n">animal_record</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="46915804" _msthash="181">并在 C 中执行以下操作：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c"><span></span><span class="tok-k">struct</span><span class="tok-w"> </span><span class="tok-nc">animal_record</span><span class="tok-w"> </span><span class="tok-n">rec</span><span class="tok-p">;</span>
<span class="tok-n">strcpy</span><span class="tok-p">(</span><span class="tok-n">rec</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-s">"Princess"</span><span class="tok-p">);</span>
<span class="tok-c1">// then, after some time, the same record is reused</span>
<span class="tok-n">strcpy</span><span class="tok-p">(</span><span class="tok-n">rec</span><span class="tok-p">.</span><span class="tok-n">name</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-s">"Sam"</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="92428648" _msthash="182">第一次操作后，缓冲区将如下所示：</font><code>strcpy</code></p>
</div>
<div class="literalblock">
<div class="content">
<pre>50 72 69 6e|63 65 73 73|00 ?? ?? ??|?? ?? ?? ??| |Princess.???????|</pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="107020810" _msthash="183">在第二个之后，以下内容将保留在
记忆：</font><code>strcpy</code></p>
</div>
<div class="literalblock">
<div class="content">
<pre>53 61 6d 00|63 65 73 73|00 ?? ?? ??|?? ?? ?? ??| |Sam.cess.???????|</pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1758748914" _msthash="184">实际上，缓冲区仍然是 16 个字节，但唯一有意义的
它拥有的内容最多是第一个空终止符。除此之外的一切
是缓冲区根本没有初始化的垃圾
（这些字节可以包含任何内容），或者它将包含
以前占用此缓冲区的字符串。</font><code>??</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="264489147" _msthash="185">在 Kaitai Struct 中也很容易对这种行为进行建模，
只需结合 和 ：</font><code>size</code><code>terminator</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">16</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="38743679" _msthash="186">这分 2 个步骤工作：</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>size</code><font _mstmutation="1" _msttexthash="43745507" _msthash="187">始终从流中读取 16 个字节。</font></p>
</li>
<li>
<p><code>terminator</code><font _mstmutation="1" _msttexthash="680420676" _msthash="188">，鉴于存在，仅在这些内部工作
16 个字节，使用第一个终止符字节提前缩短字符串
遇到，使应用程序免于获得所有尾随
垃圾。</font><code>size</code></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="enums" _msttexthash="69085315" _msthash="189">4.7. 枚举（命名整数常量）</h3>
<div class="paragraph">
<p _msttexthash="2240316312" _msthash="190">在许多情况下，二进制格式编码的性质决定了这一点
我们将使用某种整数常量来编码某些
实体。例如，IP 数据包使用 1 字节整数来
对有效负载的协议类型进行编码：6 表示“TCP”（为我们提供 TCP/IP），17 表示“UDP”（生成 UDP/IP），1 表示
“ICMP”。</p>
</div>
<div class="paragraph">
<p _msttexthash="1172108314" _msthash="191">可以只使用原始整数，但大多数编程
语言实际上提供了一种使用有意义的字符串名称进行编程的方法
相反。这种方法通常被称为“枚举”，它完全是
可以在 Kaitai Struct 中生成枚举：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">protocol</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">enum</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ip_protocol</span>
<span class="tok-nt">enums</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">ip_protocol</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">icmp</span>
<span class="tok-w">    </span><span class="tok-nt">6</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">tcp</span>
<span class="tok-w">    </span><span class="tok-nt">17</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">udp</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="72179692" _msthash="192">声明枚举应执行以下两项操作：</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><font _mstmutation="1" _msttexthash="1487882968" _msthash="193">我们在类型级别（即与 和 在同一级别）添加一个键。在该键中，我们添加了一个映射，它的键是枚举名称（在本例中，只声明了一个枚举，）
和 values 是另一个映射，它将整数值映射到
标识符。</font><code>enums</code><code>seq</code><code>meta</code><code>ip_protocol</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="756186184" _msthash="194">我们为每个属性添加一个参数
由该枚举表示，而不仅仅是一个原始整数。请注意，
这些属性首先必须具有某种整数类型
（即 或 ）。</font><code>enum: …​</code><code>type: u*</code><code>type: s*</code></p>
</li>
</ol>
</div>
</div>
<div class="sect2">
<h3 id="types" _msttexthash="56207697" _msthash="195">4.8. 子结构（子类型）</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1673832524" _msthash="196">如果我们需要以这种格式使用许多字符串，我们该怎么办？
写这么多重复的 - / -样式对会如此
麻烦且容易出错。不要害怕，我们可以定义另一种类型，
在同一文件中定义它，并将其用作流中的自定义类型：</font><code>my_len</code><code>my_str</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">track_title</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str_with_len</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">album_title</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str_with_len</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">artist_name</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str_with_len</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">str_with_len</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">value</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">        </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2403003148" _msthash="197">在这里，我们定义了另一个名为 的类型，我们引用它
只是通过做.类型本身是使用顶层的键定义的。这是一张地图，在里面我们可以定义为
我们想要的许多亚型。我们只定义一个，并在其中嵌套
与我们用于顶部类型描述的语法完全相同
级别 — 即相同的名称。</font><code>str_with_len</code><code>type: str_with_len</code><code>types:</code><code>seq</code></p>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="198">注意</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="143193661" _msthash="199">这里不需要，因为类型名称派生自此处的键名称。</font><code>meta/id</code><code>types</code></td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="110757348" _msthash="200">当然，实际上可以有更多级别的子类型：</p>
</div>
<div class="paragraph">
<p _msttexthash="11851632" _msthash="201">待办事项</p>
</div>
</div>
<div class="sect2">
<h3 id="_accessing_attributes_in_other_types" _msttexthash="47516794" _msthash="202">4.9. 访问其他类型的属性</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="598007345" _msthash="203">表达式语言（例如，在键中使用）允许您
不仅引用当前类型中的属性，还引用其他类型中的属性。
请看这个例子：</font><code>size</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">header</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">main_header</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">header.body_len</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">main_header</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic</span>
<span class="tok-w">        </span><span class="tok-nt">contents</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">MY-SUPER-FORMAT</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="832840216" _msthash="204">如果属性与 的类型相同，我们可以
用。但是，在本例中，我们决定拆分
main 标头添加到一个单独的子类型中，因此我们必须使用运算符（即 .</font><code>body_len</code><code>body</code><code>size: body_len</code><code>.</code><code>size: header.body_len</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1186747835" _msthash="205">可以将属性链接起来，以更深入地挖掘类型
层次结构 — 例如 .
但有时我们需要的恰恰相反：我们如何访问上层
来自较低级别类型的元素？Kaitai Struct 在这里提供了两个选项：</font><code>.</code><code>size: header.subheader_1.subsubheader_1_2.field_4</code></p>
</div>
<div class="sect3">
<h4 id="_parent"><font _mstmutation="1" _msttexthash="36348" _msthash="206">4.9.1.</font><code>_parent</code></h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="121366453" _msthash="207">可以使用特殊的伪属性来访问父属性
结构：</font><code>_parent</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">TODO</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_root"><font _mstmutation="1" _msttexthash="36491" _msthash="208">4.9.2.</font><code>_root</code></h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1574771536" _msthash="209">在某些情况下，写大量或根本不可能（如果你是
描述一种可能在几个不同级别上使用的类型，因此
需要不同数量的）。在这种情况下，我们可以使用
特殊的伪属性，从非常开始导航
顶级类型：</font><code>_parent._parent._parent._parent...</code><code>_parent</code><code>_root</code></p>
</div>
<div class="paragraph">
<p _msttexthash="11851632" _msthash="210">待办事项</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">header</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">main_header</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">main_header</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">magic</span>
<span class="tok-w">        </span><span class="tok-nt">contents</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">MY-SUPER-FORMAT</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">subbody_len</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_conditionals" _msttexthash="7572773" _msthash="211">4.10. 条件</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1377185706" _msthash="212">某些协议和文件格式具有可选字段，这些字段仅存在
在某些情况下。例如，可以先有一些字节
指定是否存在其他字段 （1） 或不存在 （0）。在 Kaitai Struct 中，您可以做到这一点
使用密钥：</font><code>if</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_crc32</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">crc32</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_crc32 != 0</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2491495552" _msthash="213">在此示例中，我们再次使用表达式语言来指定布尔值
表达式。如果该表达式为 true，则解析该字段并
我们会得到一个结果。如果该表达式为 false，则将跳过该字段
我们将得到一个（或其在我们的目标中最接近的等价物
编程语言）如果我们试图得到它。</font><code>if</code><code>null</code></p>
</div>
<div class="paragraph">
<p _msttexthash="1427863671" _msthash="214">在这一点上，您可能想知道它如何与枚举一起使用。
将某个整数标记为“枚举”后，它不再只是一个整数，
所以你不能直接把它和数字比较。相反，你是
预计会将其与其他枚举值进行比较：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_animal</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">enum</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">animal</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">dog_tag</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-c1"># Comparing to enum literal</span>
<span class="tok-w">    </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_animal == animal::dog</span>
<span class="tok-nt">enums</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">animal</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">cat</span>
<span class="tok-w">    </span><span class="tok-nt">2</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">dog</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="187554757" _msthash="215">还有其他可用的枚举运算，我们将在
稍后的表达语言指南。</p>
</div>
</div>
<div class="sect2">
<h3 id="_repetitions" _msttexthash="9703590" _msthash="216">4.11. 重复</h3>
<div class="paragraph">
<p _msttexthash="948763907" _msthash="217">大多数现实生活中的文件格式并不只包含某些文件格式的一个副本
元素，但可能包含多个副本，即它们重复相同的内容
一遍又一遍地模式。重复可能是：</p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="34465912" _msthash="218">元素重复到流的末尾</p>
</li>
<li>
<p _msttexthash="41454556" _msthash="219">元素重复预定义的次数</p>
</li>
<li>
<p _msttexthash="202638579" _msthash="220">元素在某个条件不满足时重复（或直到某些条件
条件变为真）</p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="970003411" _msthash="221">Kaitai Struct 支持所有这些类型的重复。在所有情况下，它都会创建
可调整大小的数组（或目标语言中最接近的等效数组）
并用元素填充它。</p>
</div>
<div class="sect3">
<h4 id="repeat-eos" _msttexthash="43710511" _msthash="222">4.11.1. 重复直到流结束</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="122004480" _msthash="223">这是最简单的重复类型，通过指定 .例如：</font><code>repeat: eos</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">numbers</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">eos</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="1801791537" _msthash="224">这将生成一个无符号整数数组，每个整数的长度为 4 个字节，其中
跨度直到流的尽头。请注意，如果我们在
不能被 4 整除的流（例如，7），我们最终将读取
尽可能多地，然后解析过程将抛出一个
流结束异常。</p>
</div>
<div class="paragraph">
<p _msttexthash="308498970" _msthash="225">当然，你可以用任何类型来做到这一点，
包括用户定义类型（子类型）：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">filenames</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">filename</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">eos</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">filename</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">8</span>
<span class="tok-w">        </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ASCII</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ext</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">3</span>
<span class="tok-w">        </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ASCII</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="291598489" _msthash="226">这定义了 类型的记录数组。每个个体都由 ASCII 中的 8 字节和 3 字节字符串组成
编码。</font><code>filename</code><code>filename</code><code>name</code><code>ext</code></p>
</div>
</div>
<div class="sect3">
<h4 id="_repeat_for_a_number_of_times" _msttexthash="22087741" _msthash="227">4.11.2. 重复多次</h4>
<div class="paragraph">
<p _msttexthash="1088330412" _msthash="228">可以重复一定次数的元素。为此，我们将
需要一个能给我们迭代次数的表达式（这将
正好是结果数组中的项数）。这可能是一个简单的
常量正好读取 12 个数字：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">numbers</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">12</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="228378605" _msthash="229">或者我们可以在这里引用一些属性来获得一个长度为
在格式中指定：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_floats</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">floats</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">f8</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_floats</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="255306532" _msthash="230">或者，使用表达式语言，我们甚至可以做一些更复杂的数学运算
它：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">width</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">height</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">matrix</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">f8</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">width * height</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1898896207" _msthash="231">这个首先指定矩阵的 and，然后解析
填充×矩阵所需的任意数量的元素
（尽管请注意，它不会是一个真正的 2D 矩阵：它仍然只是
一个常规的一维数组，您需要将 （x， y） 坐标转换为
该 1D 数组中的索引手动）。</font><code>width</code><code>height</code><code>matrix</code><code>width</code><code>height</code></p>
</div>
</div>
<div class="sect3">
<h4 id="_repeat_until_condition_is_met" _msttexthash="50267685" _msthash="232">4.11.3. 重复直到满足条件</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="962190736" _msthash="233">某些格式不指定数组中的元素数，而是指定
只需使用某种特殊元素作为表示结束的终止符即可
的数据。Kaitai Struct 也可以使用语法来做到这一点，因为
例：</font><code>repeat-until</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">numbers</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">s4</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">until</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-until</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_ == -1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="861280212" _msthash="234">这个读取 4 字节有符号整数，直到遇到 .上
遇到 ，循环将停止并进一步对元素进行排序（如果
any） 将被处理。请注意，它仍将添加到数组中。</font><code>-1</code><code>-1</code><code>-1</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="635693188" _msthash="235">下划线 （） 用作特殊变量名称，用于指代
元素。解析用户类型数组时，它
可以编写一个引用某些
该用户类型中的属性：</font><code>_</code><code>repeat-until</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">records</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">buffer_with_len</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">until</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-until</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_.len == 0</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">buffer_with_len</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">value</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="tlv" _msttexthash="145125981" _msthash="236">4.12. 典型的TLV实现（在表达式上切换类型）</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="5081849292" _msthash="237">“TLV”代表“type-length-value”，它是
多种格式。基本思想是，我们使用模块化和
反向兼容格式。在顶层，这很简单：我们知道
整个格式只是一个记录数组（或）。每条记录的开头都相同：有一些标记
指定记录的<em _mstmutation="1" _istranslated="1">类型</em>和指定记录<em _mstmutation="1" _istranslated="1">长度</em>的整数。之后，记录的正文和正文格式紧随其后
取决于<em _mstmutation="1" _istranslated="1">类型</em>标记。可以很容易地指定该基本记录
Kaitai Struct 中的大纲如下：</font><code>repeat: eos</code><code>repeat: expr</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="358102420" _msthash="238">但是，我们如何指定格式取决于？正如我们所看到的，其中一种方法是使用条件
以前：</font><code>body</code><code>rec_type</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_1</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type == 1</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_2</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_2</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type == 2</span>
<span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_unidentified</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type != 1 and rec_type != 2</span><span class="tok-w"> </span><span class="tok-c1"># and ...</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="161314894" _msthash="239">但是，很容易看出为什么它不是一个很好的解决方案：</p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="52987649" _msthash="240">我们最终写了很多重复的行</p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="411148439" _msthash="241">我们在一个类型中创建了很多属性，而实际上只有
一个会存在——其他一切都无法进行比较
因此将为 null</font><code>body_*</code><code>body</code><code>if</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="1111108505" _msthash="242">如果我们想赶上“else”分支，即匹配所有不匹配的内容
与我们的 s 匹配，我们必须写出 s 之和的倒数
手动地。对于超过 1 或 2 种类型的任何东西，它很快就会变得一团糟。</font><code>if</code><code>if</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="312782964" _msthash="243">这就是为什么 Kaitai Struct 提供了另一种解决方案。我们可以使用开关类型
操作：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_1</span>
<span class="tok-w">        </span><span class="tok-nt">2</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_2</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="6116955975" _msthash="244">这更简洁，更易于维护，不是吗？并注意
这是在属性级别指定的，因此它适用于所有
可能的类型值，为我们设置了一个很好的硬限制。更棒的是——
即使您错过了比赛，只要您指定了，
您仍然会解析给定大小，但不是
用某些用户类型解释它，它将被视为没有 ，从而产生一个原始字节数组。这非常有用，因为它
允许您逐步处理类似 TLV 的格式，从
仅支持 1 或 2 种类型的记录，并逐渐添加更多和
更多类型。</font><code>size</code><code>size</code><code>body</code><code>type</code></p>
</div>
<div class="admonitionblock caution">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5855720" _msthash="245">谨慎</div>
</td>
<td class="content">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="672857263" _msthash="246">需要确保使用的类型和使用的类型
in 要么相同，要么至少具有可比性。例如
将字符串与整数进行比较将产生编译时错误：</font><code>switch-on</code><code>cases</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_1</span>
<span class="tok-w">        </span><span class="tok-nt">2</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_2</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="308126546" _msthash="247">在这里，被声明为一个字符串，案例正在将其与
整数。所以，编译器会抱怨：</font><code>rec_type</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code><span></span>/seq/1/type/cases/IntNum(1): can't compare StrFromBytesType(...) and Int1Type(true)</code></pre>
</div>
</div>
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="304434884" _msthash="248">您可以使用“_”作为默认 （else） 大小写，它将匹配每个
未明确列出的其他值。</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_1</span>
<span class="tok-w">        </span><span class="tok-nt">2</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_2</span>
<span class="tok-w">        </span><span class="tok-nt">_</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_unknown</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="311001587" _msthash="249">切换类型可能是一种非常有用的技术。对于更高级
使用示例，请参见<a href="https://doc.kaitai.io/user_guide.html#switch-advanced" _istranslated="1">高级切换</a>。</p>
</div>
</div>
<div class="sect2">
<h3 id="_instances_data_beyond_the_sequence" _msttexthash="59066514" _msthash="250">4.13. 实例：序列之外的数据</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1589794336" _msthash="251">到目前为止，我们已经完成了所有的数据规范——因此它们将
从流的开头立即解析，一个接一个，在
严格的顺序。但是，如果您想要的数据位于其他位置怎么办
在文件中的位置，还是不按顺序出现？</font><code>seq</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="356231187" _msthash="252">“实例”是 Kaitai Struct 对此的回答。它们被指定
在与 . 相同的键中。请看这个例子：</font><code>instances</code><code>seq</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">big_file</span>
<span class="tok-w">  </span><span class="tok-nt">endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">le</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">some_integer</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x400000</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-nt">a_string</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x500fff</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x11</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ASCII</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="5188985633" _msthash="253">在里面，我们需要创建一个地图：该地图中的键是
属性名称和值以与
我们本来会这样做的，但还有一个重要的附加功能
特点：使用一个可以指定一个位置开始解析
该属性来自（以流开头的字节为单位）。正如
在 中，可以使用表达式语言并引用其他语言
中的属性。这经常用于允许访问文件
当我们有一些文件索引数据时，容器文件中的正文：文件
在容器中的位置和长度：</font><code>instances</code><code>seq</code><code>pos: …​</code><code>size</code><code>pos</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_name</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">8 + 3</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ASCII</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_offset</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_size</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">body</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_offset</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_size</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="11686734865" _msthash="254">属性和属性之间的另一个非常重要的区别是，默认情况下，实例是惰性的。有什么作用
那是什么意思？除非有人会调用该 getter 方法
以编程方式，不会进行任何实际解析。这是
对于解析较大的文件（例如文件系统的图像）非常有用。它
对于文件系统用户来说，加载所有文件系统数据是不切实际的
立即进入内存：通常通过其名称找到文件（遍历
文件索引，然后可以立即访问文件。如果
这是第一次访问此文件，将加载
（并解析）到 RAM 中。第二次和所有后续时间都会回来
来自RAM的缓存副本，避免任何不必要的重新加载/
重新解析，从而节省 RAM 和 CPU 时间。</font><code>seq</code><code>instances</code><code>body</code><code>body</code><code>body</code><code>body</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="478073817" _msthash="255">请注意，从编程的角度来看（从目标
编程语言和内部 Kaitai Struct 的表达式
language）、属性和是完全一样的。</font><code>seq</code><code>instances</code></p>
</div>
</div>
<div class="sect2">
<h3 id="_value_instances" _msttexthash="10902619" _msthash="256">4.14. 值实例</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1223399671" _msthash="257">有时，转换数据（使用表达式）很有用
language），并将其存储为命名值。还有另一种
实例 — 值实例。他们非常
简单易用，其中只有一个键 — — 指定一个
要计算的表达式：</font><code>value</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">length_in_feet</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">f8</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">length_in_m</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">length_in_feet * 0.3048</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="750810307" _msthash="258">值实例不执行实际分析，因此不需要键或键（类型将自动派生）。如果你需要
若要强制执行表达式的类型，请参阅<a href="https://doc.kaitai.io/user_guide.html#typecast" _mstmutation="1" _istranslated="1">类型转换</a>。</font><code>pos</code><code>type</code></p>
</div>
</div>
<div class="sect2">
<h3 id="_bit_sized_integers" _msttexthash="28399358" _msthash="259">4.15. 位大小的整数</h3>
<div class="paragraph">
<p _msttexthash="1087257015" _msthash="260">相当多的协议和文件格式，尤其是那些旨在
节省空间，使用整数将多个整数打包成一个字节
大小小于 8 位。例如，IPv4 数据包以字节开头
它同时包含版本号和标头长度：</p>
</div>
<div class="literalblock">
<div class="content">
<pre>76543210
vvvvllll
  │   │
  │   └─ header length
  └───── version</pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="143902265" _msthash="261">可以使用老式的
在值实例中具有按位运算的方法：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">packed_1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">version</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">(packed_1 &amp; 0b11110000) &gt;&gt; 4</span>
<span class="tok-w">  </span><span class="tok-nt">len_header</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w">  </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">packed_1 &amp; 0b00001111</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="299095732" _msthash="262">然而，Kaitai Struct 提供了一种更好的方法来做到这一点——使用<strong _istranslated="1">位大小的整数</strong>。</p>
</div>
<div class="sect3">
<h4 id="bit-ints-be" _msttexthash="23803585" _msthash="263">4.15.1. 大端顺序</h4>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="7057479" _msthash="264">重要</div>
</td>
<td class="content" _msttexthash="39918151" _msthash="265">从 v0.6 开始提供的功能。</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="127247016" _msthash="266">下面介绍如何使用 Kaitai Struct 解析上述 IPv4 示例：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">bit-endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">be</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">version</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_header</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b4</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2543302424" _msthash="267">使用密钥，我们指定 <strong _mstmutation="1" _istranslated="1">big-endian</strong> 位字段顺序
（有关详细信息，请参阅<a href="https://doc.kaitai.io/user_guide.html#bit-endian" _mstmutation="1" _istranslated="1">指定位字节序</a>）。在这种模式下，Kaitai Struct 开始解析位
从最高有效位 （MSB， 7） 到最低有效位的字段
（LSB，0）。在这种情况下，“版本”排在第一位，“len_header”排在第二位。</font><code>meta/bit-endian</code></p>
</div>
<div class="paragraph">
<p _msttexthash="65374361" _msthash="268">上述示例的位布局如下所示：</p>
</div>
<div class="literalblock">
<div class="content">
<pre>             d[0]
7   6   5   4   3   2   1   0
v3  v2  v1  v0  h3  h2  h1  h0
───────┬──────  ───────┬──────
    version       len_header</pre>
</div>
</div>
<div class="paragraph">
<p><code>d[0]</code><font _mstmutation="1" _msttexthash="307342490" _msthash="269">是流的第一个字节，行上的数字 7-0
下面表示此字节的初始位（从 MSB 到 LSB 列出）。</font><code>7</code><code>0</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="675109747" _msthash="270">的值可以检索为 <em _mstmutation="1" _istranslated="1">（<code _istranslated="1">0b...</code>） 是许多编程中存在的二进制整数文字
languages，<code _istranslated="1">{v3}</code> 是相应位的值 <code _istranslated="1">0</code> 或 <code _istranslated="1">1</code>）</em>，
并且该值可以检索为 。</font><code>version</code><code>0b{v3}{v2}{v1}{v0}</code><code>len_header</code><code>0b{h3}{h2}{h1}{h0}</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="657244393" _msthash="271">使用（其中要读取的位数）非常
用途广泛，可用于读取字节未对齐的数据。更复杂的
打包示例，其中值跨越两个字节：</font><code>type: bX</code><code>X</code></p>
</div>
<div class="literalblock">
<div class="content">
<pre>               d[0]                              d[1]
  7   6   5   4   3   2   1   0     7   6   5   4   3   2   1   0
  a4  a3  a2  a1  a0  b8  b7  b6    b5  b4  b3  b2  b1  b0  c1  c0
  ─────────┬────────  ─────────────────┬──────────────────  ───┬──
           a                           b                       c
 │ ───────────────────────────&gt; │  │ ───────────────────────────&gt; │
        parsing direction       ╷  ↑
                                └┄┄┘</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">bit-endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">be</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">a</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b5</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b9</span>
<span class="tok-w">    </span><span class="tok-c1"># 3 bits (b{8-6}) + 6 bits (b{5-0})</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">c</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b2</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="272">注意</div>
</td>
<td class="content">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1991549326" _msthash="273">为什么这个位域成员的顺序被称为“big-endian”？因为
解析结果等同于首次读取打包的
<em _mstmutation="1" _istranslated="1">按 big-endian</em> 字节顺序排列的整数，然后提取值
按顺序使用按位运算符 （ 和 ）。
下面是使用这种传统方法重写的上述示例：</font><code>&amp;</code><code>&gt;&gt;</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">packed</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2be</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">a</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">(packed &amp; 0b11111000_00000000) &gt;&gt; (3 + 8)</span>
<span class="tok-w">  </span><span class="tok-nt">b</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">(packed &amp; 0b00000111_11111100) &gt;&gt; 2</span>
<span class="tok-w">  </span><span class="tok-nt">c</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w">  </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">packed &amp; 0b00000000_00000011</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="533451854" _msthash="274">使用相同的逻辑，little-endian 位整数对应于
而是解压缩<strong _istranslated="1">一个小端</strong>整数。有关详细信息，请参阅 <a href="https://doc.kaitai.io/user_guide.html#bit-ints-le" _istranslated="1">Little-endian 顺序</a>。</p>
</div>
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="388970114" _msthash="275">或者，它可用于解析完全未对齐的比特流
重复。在此示例中，我们解析任意数量的 3 位
值：</p>
</div>
<div class="literalblock">
<div class="content">
<pre>             d[0]     d[1]     d[2]     d[3]
           76543210 76543210 76543210 76543210
           nnnnnnnn 00011122 23334445 55666777 ...
           ________ ‾‾‾___‾‾‾‾___‾‾‾____
               ╷     │  ╷  │   ╷  │   ╷
num_threes ────┘     │  │  │   │  │   │
threes[0]  ──────────┘  │  │   │  │   │
threes[1]  ─────────────┘  │   │  │   │
threes[2]  ────────────────┘   │  │   │
threes[3]  ────────────────────┘  │   │
threes[4]  ───────────────────────┘   │
threes[5]  ───────────────────────────┘
  ...</pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">bit-endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">be</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_threes</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">threes</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b3</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_thress</span></code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="7057479" _msthash="276">重要</div>
</td>
<td class="content">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1061213088" _msthash="277">默认情况下，如果混合使用“正常”字节大小的整数（即 ， ）和位大小的整数（即 ），字节大小的整数将是
保持字节对齐。这意味着，如果您这样做：</font><code>uX</code><code>sX</code><code>bX</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">bit-endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">be</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">foo</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b6</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">bar</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="55485911" _msthash="278">两个字节将像这样解析：</p>
</div>
<div class="literalblock">
<div class="content">
<pre>    76543210 76543210
    ffffff   bbbbbbbb
    ──┬───   ───┬────
      |         |
foo ──┘         |
bar ────────────┘</pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="212460976" _msthash="279">即第一个字节的两个最低有效位将丢失，并且
由于对齐而未解析。</p>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect3">
<h4 id="bit-ints-le" _msttexthash="18468762" _msthash="280">4.15.2. 小端阶</h4>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="7057479" _msthash="281">重要</div>
</td>
<td class="content" _msttexthash="39918580" _msthash="282">从 v0.9 开始提供的功能。</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="1616467021" _msthash="283">大多数格式使用小端<em _istranslated="1">字节顺序</em>和打包的多字节
位字段（例如 <a href="https://formats.kaitai.io/android_img/" _istranslated="1">android_img</a>、<a href="https://formats.kaitai.io/rar/" _istranslated="1">rar</a> 或 <a href="https://formats.kaitai.io/swf/" _istranslated="1">swf</a>）
假设使用按位运算符手动解压缩此类位字段
从预先解析的包含整个位的 little-endian 整数
田。字段的位布局是相应地设计的。</p>
</div>
<div class="paragraph">
<p _msttexthash="63830663" _msthash="284">例如，请考虑以下位字段：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">packed</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2le</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">a</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">(packed &amp; 0b11111000_00000000) &gt;&gt; (3 + 8)</span>
<span class="tok-w">  </span><span class="tok-nt">b</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">(packed &amp; 0b00000111_11111100) &gt;&gt; 2</span>
<span class="tok-w">  </span><span class="tok-nt">c</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w">  </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">packed &amp; 0b00000000_00000011</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="698949511" _msthash="285">用于提取值的表达式看起来与
对于<a href="https://doc.kaitai.io/user_guide.html#bit-ints-be" _mstmutation="1" _istranslated="1">大端顺序</a>，但实际的位布局
会有所不同，因为这里读取整数
按 little-endian （LE） 字节顺序排列。</font><code>packed</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1588340884" _msthash="286">假设这是一个 2 字节数组，需要解析无符号的 2 字节数组
integer，BE 整数的数值为 <em _mstmutation="1" _istranslated="1">（<code _istranslated="1">0x...</code> 是十六进制整数文字
<code _istranslated="1">{d[0]}</code> 是十六进制转储中所示的字节 <code _istranslated="1">d[0]</code> 的十六进制值，
例如 <code _istranslated="1">02</code> 或 <code _istranslated="1">7f</code>），</em>而 LE 整数的值
将。</font><code>d</code><code>0x{d[0]}{d[1]}</code><code>0x{d[1]}{d[0]}</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="519168403" _msthash="287">因此，如果我们从一个新的字节数组（即 反转），我们会得到相同的结果
就像从原始数组中读取 LE 整数时一样。</font><code>[d[1], d[0]]</code><code>d</code><code>d</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="951425241" _msthash="288">因为我们已经解释了位整数如何在<a href="https://doc.kaitai.io/user_guide.html#bit-ints-be" _mstmutation="1" _istranslated="1">大端顺序</a>中工作，所以让我们对
字节数组上的上述位字段反转 （），然后
将字节交换回 （） 的原始顺序：</font><code>d</code><code>d[1] d[0]</code><code>d</code><code>d[0] d[1]</code></p>
</div>
<div class="literalblock">
<div class="content">
<pre>               d[1]                              d[0]
  7   6   5   4   3   2   1   0     7   6   5   4   3   2   1   0
  a4  a3  a2  a1  a0  b8  b7  b6    b5  b4  b3  b2  b1  b0  c1  c0
  ──────────────┬───────────────    ───────────────┬──────────────
                └──────────────╷   ╷───────────────┘
                                ╲ ╱
                                 ╳
                                ╱ ╲
                ┌──────────────╵   ╵──────────────┐
               d[0]                              d[1]
  7   6   5   4   3   2   1   0     7   6   5   4   3   2   1   0
  b5  b4  b3  b2  b1  b0  c1  c0    a4  a3  a2  a1  a0  b8  b7  b6
  ──────────┬───────────  ──┬───    ─────────┬────────  ────┬─────
            b               c                a              b
│ &lt;──────────────────────────── │  │ &lt;──────────────────────────── │
╷       parsing direction                                          ↑
└┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈&gt;┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┘</pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="13964288" _msthash="289">As you can guess from the bit layout, you can’t use <a href="https://doc.kaitai.io/user_guide.html#bit-ints-be" _mstmutation="1">big-endian
bit integers</a> here without splitting the  value into 2 separate
members.</font><code>b</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="85903233" _msthash="290">This is because each byte in a <strong _mstmutation="1">big-endian</strong> bit field is gradually "filled"
with members from the most significant bit (7) to the least significant (0),
and if the current byte is filled up to LSB, the parsing continues on
MSB of next byte. It follows that  really can’t be represented
with a single attribute using this order, because  and  are standing
in the way.</font><code>b</code><code>c</code><code>a</code></p>
</div>
<div class="paragraph">
<p _msttexthash="31483465" _msthash="291">Little-endian bit fields use the reversed parsing direction: bytes are filled
from LSB (0) to MSB (7), and after filling the byte up to MSB, values
overflow to the next byte’s LSB.</p>
</div>
<div class="paragraph">
<p _msttexthash="5815771" _msthash="292">For example, the above bit layout can be conveniently represented using
little-endian bit integers:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">bit-endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">le</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">c</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b2</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b9</span>
<span class="tok-w">    </span><span class="tok-c1"># 6 bits (b{5-0}) + 3 bits (b{8-6})</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">a</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b5</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="58433219" _msthash="293">As you can see in the KSY snippet, the bit field members in 
are listed from the least significant value to the most significant.
If we look at the bit masks of bit field members (which can be
directly used for ANDing  with the 2-byte little-endian unsigned
value), they would be sorted in <strong _mstmutation="1">ascending</strong> order (starting with
the <em _mstmutation="1">least significant</em> value):</font><code>seq</code><code>&amp;</code></p>
</div>
<div class="literalblock">
<div class="content">
<pre>c    0b00000000_00000011
b    0b00000111_11111100
a    0b11111000_00000000</pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="17968522" _msthash="294">This may seem strange at first, but it’s actually natural from the
perspective of how little-endian bit fields work, and how they
physically store their members.</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="80646592" _msthash="295">Thanks to this order, Kaitai Struct <strong _mstmutation="1">doesn’t need</strong> to know the byte
size of the whole bitfield in advance <em _mstmutation="1">(so that its members could
be rearranged at compile-time to match their physical location)</em>,
and it can normally parse the attributes on the run.
It follows that little-endian bit-sized integers can be normally
combined with  conditions and repetitions like any other Kaitai Struct type.</font><code>if</code></p>
</div>
</div>
<div class="sect3">
<h4 id="bit-endian" _msttexthash="837304" _msthash="296">4.15.3. Specifying bit endianness</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="14407835" _msthash="297">The key  specifies the default parsing direction
(<em _mstmutation="1">bit endianness</em>) of bit-sized integers. It can only have the
literal value  or  (run-time <a href="https://doc.kaitai.io/user_guide.html#calc-endian" _mstmutation="1">switching</a>
is <strong _mstmutation="1">not</strong> supported).</font><code>meta/bit-endian</code><code>le</code><code>be</code></p>
</div>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="138944" _msthash="298">Important</div>
</td>
<td class="content">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="11435229" _msthash="299">Support for  was added in <strong _mstmutation="1">v0.9</strong>
(previously only BE direction was supported). To maintain
backward compatibility, the big-endian order () is default.</font><code>meta/bit-endian</code><code>be</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="25357930" _msthash="300">However, if you don’t really need to support pre-0.9 KSC
versions, it’s recommended to state 
<em _mstmutation="1">explicitly</em>, because it raises awareness about the existence
of LE bit endianness.</font><code>meta/bit-endian: be</code></p>
</div>
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="13558246" _msthash="301">Like ,  also applies to  attributes
in the current type and all subtypes, but it can be overridden
using the / suffix (/) for the individual bit
integers. For example:</font><code>meta/endian</code><code>meta/bit-endian</code><code>bX</code><code>le</code><code>be</code><code>bXle</code><code>bXbe</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">bit-endian</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">le</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">foo</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b2</span><span class="tok-w"> </span><span class="tok-c1"># little-endian</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">my_subtype</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">bar</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b8</span><span class="tok-w"> </span><span class="tok-c1"># also little-endian</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">baz</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b16be</span><span class="tok-w"> </span><span class="tok-c1"># big-endian</span></code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="138944" _msthash="302">Important</div>
</td>
<td class="content">
<div class="paragraph">
<p _msttexthash="44427643" _msthash="303"><em>Big-endian</em> and <em>little-endian</em> bit integers can follow <strong>only on a byte
boundary</strong>. They can’t share the same byte. Joining them on an
unaligned bit position is <em>undefined behavior</em>, and future versions of KSC will throw
a compile-time error if they detect such a situation.</p>
</div>
<div class="paragraph">
<p _msttexthash="622583" _msthash="304">For example, this is <strong>illegal</strong>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">foo</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b4be</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">bar</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">b4le</span></code></pre>
</div>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ksy-documentation" _msttexthash="590408" _msthash="305">4.16. Documenting your spec</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="33165964" _msthash="306">We introduced the  key <a href="https://doc.kaitai.io/user_guide.html#docstrings" _mstmutation="1">early in this user guide</a> as
a simple way to add docstrings to the attributes. However, it’s not
only attributes that can be documented. The same  key can be used
in several different contexts:</font><code>doc</code><code>doc</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">|</span>
<span class="tok-w">  </span><span class="tok-no">Documentation for type. Works for top-level types too, in case you</span>
<span class="tok-w">  </span><span class="tok-no">were wondering.</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">attr_1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Documentation for sequence attribute.</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">attr_2</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x1234</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Documentation for parse instance attribute.</span>
<span class="tok-w">  </span><span class="tok-nt">attr_3</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">attr_2 + 1</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Documentation for value instance attribute.</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">some_type</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Documentation for type as well. Works for inner types too.</span>
<span class="tok-nt">params</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">param_1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">|</span>
<span class="tok-w">      </span><span class="tok-no">Documentation for a parameter. Parameters are a relatively</span>
<span class="tok-w">      </span><span class="tok-no">advanced topic, see below for the explanations.</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="doc-ref"><font _mstmutation="1" _msttexthash="44265" _msthash="307">4.16.1. </font><code>doc-ref</code></h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="79269827" _msthash="308">The  key has a "sister" key , which can be used to specify
references to original documentation. This is very useful to keep
track of what corresponds to what when transcribing an existing
specification. Everywhere where you can use , you can use
 as well. Depending on the target language, this key would be
rendered as something akin to a "see also" extra paragraph after the
main docstring. For example:</font><code>doc</code><code>doc-ref</code><code>doc</code><code>doc-ref</code></p>
</div>
<table class="tableblock frame-none grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="title" _msttexthash="205257" _msthash="309">Kaitai Struct</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_record</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Total length of record in bytes.</span>
<span class="tok-w">    </span><span class="tok-nt">doc-ref</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ISO spec, section 1.2.3</span></code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="title" _msttexthash="43238" _msthash="310">Java</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-cm">/**</span>
<span class="tok-cm"> * Total length of record in bytes.</span>
<span class="tok-cm"> * @see "ISO-9876 spec, section 1.2.3"</span>
<span class="tok-cm"> */</span>
<span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kt">int</span><span class="tok-w"> </span><span class="tok-nf">lenRecord</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-p">{</span><span class="tok-w"> </span><span class="tok-k">return</span><span class="tok-w"> </span><span class="tok-n">lenRecord</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-p">}</span></code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="463216" _msthash="311">Inside , one can specify:</font><code>doc-ref</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="12616149" _msthash="312">Just a user-readable string. Most widely used to reference offline documentation. User would need to find relevant portion of documentation manually.</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">doc-ref</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ISO-9876 spec, section 1.2.3</span></code></pre>
</div>
</div>
</li>
<li>
<p _msttexthash="23160462" _msthash="313">Just a link. Used when existing documentation has a non-ambiguous,
well defined URL that everyone can refer to, and there’s nothing
much to add to it.</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">doc-ref</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">https://www.youtube.com/watch?v=dQw4w9WgXcQ</span></code></pre>
</div>
</div>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="135273723" _msthash="314">Link + description. Used when adding some extra text information is
beneficial: for example, when a URL is not enough and needs some
comments on how to find relevant info inside the document, or the
document is also accessible through some other means and it’s useful
to specify both URL and section numbering for those who won’t be
using the URL. In this case,  is composed of a URL, then a space,
then a description.</font><code>doc-ref</code></p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">doc-ref</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">https://tools.ietf.org/html/rfc2795#section-6.1 RFC2795, 6.1 "SIMIAN Client Requests"</span></code></pre>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="orig-id"><font _mstmutation="1" _msttexthash="44421" _msthash="315">4.16.2. </font><code>-orig-id</code></h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="115692122" _msthash="316">When transcribing spec based on some existing implementation, most
likely you won’t be able to keep exact same spelling of all
identifiers. Kaitai Struct imposes pretty draconian rules on what can
be used as , and there is a good reason for it: different target
languages have different ideas of what constitutes a good identifier,
so Kaitai Struct had to choose some "middle ground" that yields decent
results when converted to all supported languages' standards.</font><code>id</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="12336051" _msthash="317">However, in many cases, it might be useful to keep references to how
things were named in original implementation. For that, one can
customarily use  key:</font><code>-orig-id</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_str_buf</span>
<span class="tok-w">    </span><span class="tok-nt">-orig-id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">StringBufferSize</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str_buf</span>
<span class="tok-w">    </span><span class="tok-nt">-orig-id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">StringDataInputBuffer</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_str_buf</span></code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="31668" _msthash="318">Tip</div>
</td>
<td class="content">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="112164871" _msthash="319">The Kaitai Struct compiler will just ignore any key that starts with
, and silently allow it. These kind of keys can be used to store
arbitrary additional information, which can be accessible to external
tools (i.e. other than the compiler). Feel free to add more arbitrary
keys if you need to store extra structured information for some
reason. For example, if you have 2 concurrent existing implementations
in C++ and Java, you can store IDs for both of them for future
reference:</font><code>-</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">foo_bar</span>
<span class="tok-w">    </span><span class="tok-nt">-getter-id-cpp</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">get_foo_bar()</span>
<span class="tok-w">    </span><span class="tok-nt">-getter-id-java</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">getFooBar()</span></code></pre>
</div>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect3">
<h4 id="verbose-enums" _msttexthash="371332" _msthash="320">4.16.3. Verbose enums</h4>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="138944" _msthash="321">Important</div>
</td>
<td class="content" _msttexthash="604513" _msthash="322">
Feature available since v0.8.
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="5502055" _msthash="323">If you want to add some documentation for enums, this is possible
using verbose enums declaration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">enums</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">ip_protocol</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">1</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">icmp</span>
<span class="tok-w">      </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Internet Control Message Protocol</span>
<span class="tok-w">      </span><span class="tok-nt">doc-ref</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">https://www.ietf.org/rfc/rfc792</span>
<span class="tok-w">    </span><span class="tok-nt">6</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">tcp</span>
<span class="tok-w">      </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Transmission Control Protocol</span>
<span class="tok-w">      </span><span class="tok-nt">doc-ref</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">https://www.ietf.org/rfc/rfc793</span>
<span class="tok-w">    </span><span class="tok-nt">17</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">udp</span>
<span class="tok-w">      </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">User Datagram Protocol</span>
<span class="tok-w">      </span><span class="tok-nt">doc-ref</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">https://www.ietf.org/rfc/rfc768</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="22450688" _msthash="324">In this format, instead of specifying just the identifier for every
numeric value, you specify a YAML map, which has an  key for
the identifier, and allows other regular keys (like  and )
to specify documentation.</font><code>id</code><code>doc</code><code>doc-ref</code></p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="meta" _msttexthash="285207" _msthash="325">4.17. Meta section</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="19944132" _msthash="326">The  key is used to define a section which stores meta-information
about a given type, i.e. various complimentary stuff, such as titles,
descriptions, pointers to external linked resources, etc:</font><code>meta</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>id</code></p>
</li>
<li>
<p><code>title</code></p>
</li>
<li>
<p><code>application</code></p>
</li>
<li>
<p><code>file-extension</code></p>
</li>
<li>
<p><code>xref</code><font _mstmutation="1" _msttexthash="1618669" _msthash="327"> — used to specify <a href="https://doc.kaitai.io/user_guide.html#meta-xref" _mstmutation="1">cross-references</a></font></p>
</li>
<li>
<p><code>license</code></p>
</li>
<li>
<p><code>tags</code></p>
</li>
<li>
<p><code>ks-version</code></p>
</li>
<li>
<p><code>ks-debug</code></p>
</li>
<li>
<p><code>ks-opaque-types</code></p>
</li>
<li>
<p><code>imports</code></p>
</li>
<li>
<p><code>encoding</code></p>
</li>
<li>
<p><code>endian</code></p>
</li>
</ul>
</div>
<div class="admonitionblock tip">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="31668" _msthash="328">Tip</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="24898328" _msthash="329">
While it’s technically possible to specify  keys in
arbitary order (as in any other YAML map), please use the order
recommended in the <a href="https://doc.kaitai.io/ksy_style_guide.html#meta" _mstmutation="1">KSY style guide</a> when
authoring .ksy specs for public use to improve readability.
</font><code>meta</code></td>
</tr>
</tbody></table>
</div>
<div class="sect3">
<h4 id="meta-xref" _msttexthash="502372" _msthash="330">4.17.1. Cross-references</h4>
<div class="paragraph">
<p><code>meta/xref</code><font _mstmutation="1" _msttexthash="60372962" _msthash="331"> can be used to provide arbitrary cross-references for a
particular type in other collections, such as references / IDs in
format databases, wikis, encyclopedias, archives, formal standards,
etc. Syntactically, it’s just a place where you can store arbitrary
key-value pairs, e.g.:</font></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">xref</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">forensicswiki</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">portable_network_graphics_(png)</span>
<span class="tok-w">    </span><span class="tok-nt">iso</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-s">'15948:2004'</span>
<span class="tok-w">    </span><span class="tok-nt">justsolve</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">PNG</span>
<span class="tok-w">    </span><span class="tok-nt">loc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fdd000153</span>
<span class="tok-w">    </span><span class="tok-nt">mime</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">image/png</span>
<span class="tok-w">    </span><span class="tok-nt">pronom</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fmt/13</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fmt/12</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fmt/11</span>
<span class="tok-w">    </span><span class="tok-nt">rfc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">2083</span>
<span class="tok-w">    </span><span class="tok-nt">wikidata</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">Q178051</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="8903921" _msthash="332">There are several "well-known" keys used by convention by many spec
authors to provide good cross references of their formats:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>forensicswiki</code><font _mstmutation="1" _msttexthash="18265234" _msthash="333"> specifies an article name at
<a href="https://forensics.wiki/" _mstmutation="1">Forensics Wiki</a>, which is a
CC-BY-SA-licensed wiki with information on digital forensics, file
formats and tools. A full link could be generated as
 + this value + .</font><code>https://forensics.wiki/</code><code>/</code></p>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="7410416" _msthash="334">For consistency, insert parentheses in this value literally (without
using percent-encoding) - e.g. use  instead
of .</font><code>extended_file_system_(ext)</code><code>extended_file_system_%28ext%29</code></p>
</div>
</li>
<li>
<p><code>iso</code><font _mstmutation="1" _msttexthash="125695648" _msthash="335"> specifies an ISO/IEC standard number, a reference to a standard
accepted and published by <a href="https://www.iso.org/" _mstmutation="1">ISO</a> (International
Organization for Standardization). Typically these standards are not
available for free (i.e. one has to pay to get a copy of a standard
from ISO), and it’s non-trivial to link to the ISO standards
catalogue. However, ISO standards typically have clear designations
like "ISO/IEC 15948:2004", so the value should cite everything
except for "ISO/IEC", e.g. .</font><code>15948:2004</code></p>
</li>
<li>
<p><code>justsolve</code><font _mstmutation="1" _msttexthash="15154620" _msthash="336"> specifies an article name at
<a href="http://fileformats.archiveteam.org/wiki/Main_Page" _mstmutation="1">"Just Solve the File Format
Problem" wiki</a>, a wiki that collects information on many file
formats. A full link could be generated as
 + this value.</font><code>http://fileformats.archiveteam.org/wiki/</code></p>
</li>
<li>
<p><code>loc</code><font _mstmutation="1" _msttexthash="30571229" _msthash="337"> specifies an identifier in the
<a href="https://www.loc.gov/preservation/digital/formats/fdd/browse_list.shtml" _mstmutation="1">Digital
Formats</a> database of the <a href="https://www.loc.gov/" _mstmutation="1">US Library of Congress</a>, a
major effort to enumerate and document many file formats for digital
preservation purposes. The value typically looks like , where
 is a 6-digit identifier.</font><code>fddXXXXXX</code><code>XXXXXX</code></p>
</li>
<li>
<p><code>mime</code><font _mstmutation="1" _msttexthash="48696830" _msthash="338"> specifies a
<a href="https://en.wikipedia.org/wiki/Media_type" _mstmutation="1">MIME (Multipurpose Internet
Mail Extensions) type</a>, AKA "media type" designation, a string
typically used in various Internet protocols to specify format of
binary payload. As of 2019, there is a
<a href="https://www.iana.org/assignments/media-types/media-types.xhtml" _mstmutation="1">central
registry of media types</a> managed by IANA. The value must specify the full
MIME type (both parts), e.g. .</font><code>image/png</code></p>
</li>
<li>
<p><code>pronom</code><font _mstmutation="1" _msttexthash="106941848" _msthash="339"> specifies a format identifier in the
<a href="https://www.nationalarchives.gov.uk/PRONOM/Default.aspx" _mstmutation="1">PRONOM
Technical Registry</a> of the <a href="https://www.nationalarchives.gov.uk/" _mstmutation="1">UK
National Archives</a>, which is a massive file formats database that
catalogues many file formats for digital preservation
purposes. The value typically looks like , where  is a
number assigned at PRONOM (this idenitifer is called a "PUID", AKA
"PRONOM Unique Identifier" in PRONOM itself). If many different
PRONOM formats correspond to a particular spec, specify them as a YAML
array (see example above).</font><code>fmt/xxx</code><code>xxx</code></p>
</li>
<li>
<p><code>rfc</code><font _mstmutation="1" _msttexthash="62332751" _msthash="340"> specifies a reference to
<a href="https://en.wikipedia.org/wiki/Request_for_Comments" _mstmutation="1">RFC</a>, "Request
for Comments" documents maintained by ISOC (Internet
Society). Despite the confusing name, RFCs are typically treated as
global, Internet-wide standards, and, for example, many networking /
interoperability protocols are specified in RFCs. The value should be
just the raw RFC number, without any prefixes, e.g. .</font><code>1234</code></p>
</li>
<li>
<p><code>wikidata</code><font _mstmutation="1" _msttexthash="79122485" _msthash="341"> specifies an item name at
<a href="https://www.wikidata.org/wiki/Wikidata:Main_Page" _mstmutation="1">Wikidata</a>, a global knowledge base. All
Wikimedia projects (such as language-specific Wikipedias,
Wiktionaries, etc) use Wikidata at least for connecting various
translations of encyclopedic articles on a particular subject, so
keeping just a link to Wikidata is typically enough to.  The value
typically follows a  pattern, where  is a number generated
by Wikidata, e.g. .</font><code>Qxxx</code><code>xxx</code><code>Q535473</code></p>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="stream" _msttexthash="527449" _msthash="342">5. Streams and substreams</h2>
<div class="sectionbody">
<div class="paragraph">
<p _msttexthash="47613267" _msthash="343">Imagine that we’re dealing with a structure of known size. For the sake of
simplicity, let’s say that it’s fixed to exactly 20 bytes (but all the
following is also true if the size is defined by some arbitrarily
complex expression):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">person</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">code</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">16</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="3394391" _msthash="344">When we’re invoking user-defined types, we can do either:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">joe</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">person</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="28743" _msthash="345">or:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">joe</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">person</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">20</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="55199066" _msthash="346">Note the subtle difference: we’ve skipped the  in the first example
and added it in the second one. From the end-user’s perspective, nothing
has changed. You can still access Joe’s code and name equally well in
both cases:</font><code>size</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-n">r</span><span class="tok-p">.</span><span class="tok-na">joe</span><span class="tok-p">().</span><span class="tok-na">code</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-c1">// works</span>
<span class="tok-n">r</span><span class="tok-p">.</span><span class="tok-na">joe</span><span class="tok-p">().</span><span class="tok-na">name</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-c1">// works</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="20011927" _msthash="347">However, what gets changed under the hood? It turns out that
specifying  actually brings some new features: if you modify the
 type to be less than 20 bytes long, it still reserves exactly
20 bytes for :</font><code>size</code><code>person</code><code>joe</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">joe</span><span class="tok-w">        </span><span class="tok-c1"># reads from position 0</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">person</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">20</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">foo</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span><span class="tok-w">       </span><span class="tok-c1"># reads from position 20</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">person</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-c1"># although this type is 14 bytes long now</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">code</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">10</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="12779091" _msthash="348">In this example, the extra 6 bytes would just be skipped. Alternatively,
if you make  to be more than 20 bytes long, it will
trigger an end-of-stream exception:</font><code>person</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">joe</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">person</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">20</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">foo</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">person</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-c1"># 100 bytes is longer than 20 bytes declared in `size`</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">code</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span><span class="tok-w"> </span><span class="tok-c1"># will trigger an exception here</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">96</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="4020575" _msthash="349">How does it work? Let’s take a look under the hood.</p>
</div>
<div class="paragraph">
<p _msttexthash="2925741" _msthash="350">Sizeless user type
invocation generates the following parsing code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">joe</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">Person</span><span class="tok-p">(</span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_io</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">_root</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2954003" _msthash="351">However, when we declare the , things get a little bit more
complicated:</font><code>size</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_raw_joe</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_io</span><span class="tok-p">.</span><span class="tok-na">readBytes</span><span class="tok-p">(</span><span class="tok-mi">20</span><span class="tok-p">);</span>
<span class="tok-n">KaitaiStream</span><span class="tok-w"> </span><span class="tok-n">_io__raw_joe</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">KaitaiStream</span><span class="tok-p">(</span><span class="tok-n">_raw_joe</span><span class="tok-p">);</span>
<span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">joe</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">Person</span><span class="tok-p">(</span><span class="tok-n">_io__raw_joe</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">_root</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="83221307" _msthash="352">Every class that Kaitai Struct generates carries a concept of a "stream", usually
available as an  member. This is the default stream it reads from
and writes to. This stream works just as you might expect from a
regular IO stream implementation in a typical language: it
encapsulates reading from files and memory, stores a pointer to its
current position, and allows reading/writing of various primitives.</font><code>_io</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="20652866" _msthash="353">Declaring a new user-defined type in the middle of the  attributes
generates a new object (usually via a constructor call), and this object,
in turn, needs its own IO stream. So, what are our options here?</font><code>seq</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="17993365" _msthash="354">In the "sizeless" case, we just pass the current  along to the new
object. This "reuses" the existing stream with all its properties:
current pointer position, size, available bytes, etc.</font><code>_io</code></p>
</li>
<li>
<p _msttexthash="31399875" _msthash="355">In the "sized" case, we know the size a priori and want the object we
created to be limited within that size. So, instead of passing an
existing stream, we create a new substream that will be
shorter and will contain the exact number of bytes requested.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="5280678" _msthash="356">Implementations vary from language to language, but, for example, in
Java, the following is done:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-c1">// First, we read as many bytes as needed from our current IO stream.</span>
<span class="tok-c1">// Note that if we don't even have 20 bytes right now, this will throw</span>
<span class="tok-c1">// an EOS exception on this line, and the user type won't even be invoked.</span>
<span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_raw_joe</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_io</span><span class="tok-p">.</span><span class="tok-na">readBytes</span><span class="tok-p">(</span><span class="tok-mi">20</span><span class="tok-p">);</span>

<span class="tok-c1">// Second, we wrap our bytes into a new stream, a substream</span>
<span class="tok-n">KaitaiStream</span><span class="tok-w"> </span><span class="tok-n">_io__raw_joe</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">KaitaiStream</span><span class="tok-p">(</span><span class="tok-n">_raw_joe</span><span class="tok-p">);</span>

<span class="tok-c1">// Finally, we pass our substream to the Person class instead of</span>
<span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">joe</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">Person</span><span class="tok-p">(</span><span class="tok-n">_io__raw_joe</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">_root</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="51812618" _msthash="357">After that, parsing of a  type will be totally bound to the limits
of that particular substream. Nothing in the Person class
can do a thing to the original stream — it just doesn’t have access to
that object.</font><code>person</code></p>
</div>
<div class="paragraph">
<p _msttexthash="4935411" _msthash="358">Let’s check out a few use cases that demonstrate how powerful this
practice can be.</p>
</div>
<div class="sect2">
<h3 id="_limiting_total_size_of_structure" _msttexthash="998972" _msthash="359">5.1. Limiting total size of structure</h3>
<div class="paragraph">
<p _msttexthash="2022657" _msthash="360">Quite often binary formats use the following technique:</p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="17951102" _msthash="361">First comes some integer that declares the total size of the structure
(or the structure’s body, i.e. everything minus this header).</p>
</li>
<li>
<p _msttexthash="8166496" _msthash="362">Then comes the structure’s body, which is expected to have exactly the
declared number of bytes.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="441675" _msthash="363">Consider this example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>

<span class="tok-w">  </span><span class="tok-c1"># The following must be exactly `body_len` bytes long</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">uuid</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">16</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">24</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">price</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-c1"># This "comment" entry must fill up all remaining bytes up to the</span>
<span class="tok-w">  </span><span class="tok-c1"># total of `body_len`.</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">comment</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">???</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="1079026" _msthash="364">Of course, one can derive this manually:</p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="3030781" _msthash="365">body_len = sizeof(uuid) + sizeof(name) + sizeof(price) + sizeof(comment)</p>
</li>
<li>
<p _msttexthash="820482" _msthash="366">body_len = 16 + 24 + 4 + sizeof(comment)</p>
</li>
<li>
<p _msttexthash="790894" _msthash="367">sizeof(comment) = body_len - (16 + 24 + 4)</p>
</li>
<li>
<p _msttexthash="636402" _msthash="368">sizeof(comment) = body_len - 44</p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="55393" _msthash="369">Thus:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">comment</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len - 44</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="15301039" _msthash="370">But this is very inconvenient and potentially error prone. What will
happen if at some time in future the record contents are updated
and we forget to update this formula?</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="21668920" _msthash="371">It turns out that substreams offer a much cleaner solution here. Let’s
separate our "header" and "body" into two distinct user types, and
then we can just specify  on this :</font><code>size</code><code>body</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">record_body</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len</span>
<span class="tok-w">    </span><span class="tok-c1"># ^^ This is where substream magic kicks in</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">record_body</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">uuid</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">16</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">24</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">price</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">comment</span>
<span class="tok-w">        </span><span class="tok-nt">size-eos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">true</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="18909137" _msthash="372">For , we just made its size to be up until the end of
stream. Given that we’ve limited it to the substream in the first
place, this is exactly what we wanted.</font><code>comment</code></p>
</div>
</div>
<div class="sect2">
<h3 id="repeat-until-size-limit" _msttexthash="1391065" _msthash="373">5.2. Repeating until total size reaches limit</h3>
<div class="paragraph">
<p _msttexthash="18817136" _msthash="374">The same technique might be useful for repetitions as well. If you
have an array of same-type entries, and a format declares the total size
of all entries combined, again, you can try to do this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">total_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entries</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entry</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">???</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="7679048" _msthash="375">And do some derivations to calculate number of entries,
i.e. "total_len / sizeof(entry)". But, again, this is bad because:</p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="4282720" _msthash="376">You need to keep remembering to update this "sizeof" value when
the entry size updates.</p>
</li>
<li>
<p _msttexthash="6011564" _msthash="377">If the entry size if not fixed, you’re totally out of luck here.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="11347427" _msthash="378">Solving it using substreams is much more elegant. You just create a
substream limited to  bytes, and then use  to
repeat until the end of that stream.</font><code>total_len</code><code>repeat: eos</code></p>
</div>
<div class="admonitionblock caution">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="95875" _msthash="379">Caution</div>
</td>
<td class="content">
<div class="paragraph">
<p _msttexthash="4734821" _msthash="380">However, note that one’s naïve approach might not work:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="7614854" _msthash="381">When we’re dealing with an array of elements,  will refer to
the size of one particular element of the array.</font><code>size</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="15324959" _msthash="382">Any repetition (and this includes ) parses the elements
using the current IO stream. If  is specified, substreams
are created individually for each object inside the loop.</font><code>repeat: eos</code><code>size</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="3117543" _msthash="383">So this is <strong _mstmutation="1">wrong</strong> ( determines the size
of each individual  substream here):</font><code>total_len</code><code>entry</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">total_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entries</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entry</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">total_len</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">eos</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="5830201" _msthash="384">For more information, see <a href="https://doc.kaitai.io/user_guide.html#keys-repeated">Keys relating to the whole array and to each element in repeated attributes</a>.</p>
</div>
<div class="paragraph">
<p _msttexthash="1742949" _msthash="385">The proper solution is to add an extra layer of types:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">total_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entries</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_entries</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">total_len</span>
<span class="tok-w">    </span><span class="tok-c1"># ^^ here we added the limit and created a single substream</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_entries</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entries</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entry</span>
<span class="tok-w">        </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">eos</span>
<span class="tok-w">        </span><span class="tok-c1"># ^^ repeats until the end of that limited substream</span>
<span class="tok-w">  </span><span class="tok-nt">entry</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-c1"># ...</span>
<span class="tok-w">    </span><span class="tok-c1"># Now, this can even be of variable size: that's totally ok.</span></code></pre>
</div>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="_relative_positioning" _msttexthash="553488" _msthash="386">5.3. Relative positioning</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="37521952" _msthash="387">Another useful feature that’s possible with substreams is the fact that
while you’re in a substream, the  key works in the context of that
substream as well. That means it addresses data relative to the start of that
substream:</font><code>pos</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">some_header</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">20</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">80</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">block</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">foo</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">some_bytes_in_the_middle</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">30</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">16</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="8228935" _msthash="388">In this example,  allocates a substream spanning from 20th byte
(inclusive) till 100th byte (exclusive). Then, in that stream:</font><code>body</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>foo</code><font _mstmutation="1" _msttexthash="3734211" _msthash="389"> would be parsed right from the beginning of that substream,
thus taking up bytes </font><code>[20..24)</code></p>
</li>
<li>
<p><code>some_bytes_in_the_middle</code><font _mstmutation="1" _msttexthash="6003582" _msthash="390"> would start parsing 16 bytes from the 30th
byte <strong _mstmutation="1">of that substream</strong>, thus parsing bytes  =
 in the main stream.</font><code>[20 + 30 .. 20 + 46)</code><code>[50..66)</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="65662155" _msthash="391">This comes super handy if your format’s internal structures somehow
specify offsets relative to some other structures of the format. For
example, a typical filesystem/database often uses a concept of blocks,
and offsets that address stuff inside the current block. Note how KSY with
substreams is easier to read, more concise and less error-prone:</p>
</div>
<table class="tableblock frame-none grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="title" _msttexthash="317122" _msthash="392">Bad (w/o substream)</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_block</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">some_block</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">12345 * len_block</span>
<span class="tok-w">    </span><span class="tok-c1"># no size =&gt; no substream!</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">data_block</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">data_block</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_data</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">data</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">12345 * _root.len_block + ofs_data</span>
<span class="tok-w">        </span><span class="tok-c1"># have to calculate position manually</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">40</span></code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="title" _msttexthash="317239" _msthash="393">Good (w/substream)</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_block</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">some_block</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">12345 * len_block</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_block</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">data_block</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">data_block</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_data</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">data</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_data</span>
<span class="tok-w">        </span><span class="tok-c1"># relative to data_block</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">40</span></code></pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="8800168" _msthash="394">The more levels of structure offset nesting there are, the more
complicated these  expressions would get without substreams.</font><code>pos</code></p>
</div>
</div>
<div class="sect2">
<h3 id="_absolute_positioning" _msttexthash="554931" _msthash="395">5.4. Absolute positioning</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="58920238" _msthash="396">If you ever need to "escape" the limitations of a substream by
wishing to use a  key of a parse instance to address something absolutely
(i.e. in the main stream), it’s easy to do so by adding an  key to
choose the root’s stream:</font><code>pos</code><code>io</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">some_header</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">20</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">files</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">80</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_entry</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">eos</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_entry</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_name</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_body</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_body</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">body</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">io</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_root._io</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_body</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_body</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="287980186" _msthash="397">That’s the typical situation encountered in many file container
formats. Here we have a list of , and each of its entries has
been limited to exactly 80 bytes. Inside each 80-byte chunk, there’s a
, and, more importantly, a pointer to the absolute location of
the file’s body inside the stream. The  instance allows us to get that
file’s body contents quickly and easily. Note that if there was no
 key there, that  would have been parsed inside a
80-byte substream (and most likely that would result in an exception
trying to read outside of the 80 byte limit), and that’s not what we want
here.</font><code>files</code><code>file_name</code><code>body</code><code>io: _root._io</code><code>body</code></p>
</div>
</div>
<div class="sect2">
<h3 id="_choosing_a_substream" _msttexthash="508547" _msthash="398">5.5. Choosing a substream</h3>
<div class="paragraph">
<p _msttexthash="24654591" _msthash="399">The technique above is not limited to just the root
object’s stream. You can address any other object’s stream as well,
for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">global_header</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">1024</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_one</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">big_container</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">4096</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_two</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">smaller_container</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">1024</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">big_container</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">some_header</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">8</span>
<span class="tok-w">      </span><span class="tok-c1"># the rest of the data in this container would be referenced</span>
<span class="tok-w">      </span><span class="tok-c1"># from other blocks</span>
<span class="tok-w">  </span><span class="tok-nt">smaller_container</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_in_big</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_in_big</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">something_in_big</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">io</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_root.block_one._io</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_in_big</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_in_big</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="process" _msttexthash="3229317" _msthash="400">5.6. Processing: dealing with compressed, obfuscated and encrypted data</h3>
<div class="paragraph">
<p _msttexthash="248949077" _msthash="401">Some formats obscure the data fully or partially with techniques like
compression, obfuscation or encryption. In these cases, incoming data
should be pre-processed before actual parsing takes place, or we’ll
just end up with garbage getting parsed. All such pre-processing
algorithms have one thing in common: they’re done by some function that
takes a stream of bytes and returns another stream of bytes (note that the number
of incoming and resulting bytes might be different, especially in the case
of decompression). While it might be possible to do such transformation
in a declarative manner, it is usually impractical to do so.</p>
</div>
<div class="paragraph">
<p _msttexthash="37767093" _msthash="402">Kaitai Struct allows you to plug-in some predefined "processing" algorithms
to do decompression, de-obfuscation and decryption to get a
clear stream, ready to be parsed. Consider parsing a file, in which the
main body is obfuscated by applying XOR with 0xaa for every byte:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body_len</span>
<span class="tok-w">    </span><span class="tok-nt">process</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">xor(0xaa)</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">some_body_type</span><span class="tok-w"> </span><span class="tok-c1"># defined normally later</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="126971" _msthash="403">Note that:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="2205931" _msthash="404">Applying  is available only to raw byte arrays or user
types.</font><code>process: …​</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="8362952" _msthash="405">One might use expression language inside , thus referencing
the XOR obfuscation key read into some other field
previously.</font><code>xor(…​)</code></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_expression_language" _msttexthash="443950" _msthash="406">6. Expression language</h2>
<div class="sectionbody">
<div class="paragraph">
<p _msttexthash="30882345" _msthash="407">Expression language is a powerful internal tool inside Kaitai
Struct. In a nutshell, it is a simple object-oriented, statically-typed
language that gets translated/compiled (AKA "transpiled") into any
supported target programming language.</p>
</div>
<div class="paragraph">
<p _msttexthash="16646305" _msthash="408">The language is designed to follow the principle of least surprise, so
it borrows tons of elements from other popular languages, like C,
Java, C#, Ruby, Python, JavaScript, Scala, etc.</p>
</div>
<div class="sect2">
<h3 id="_basic_data_types" _msttexthash="358475" _msthash="409">6.1. Basic data types</h3>
<div class="paragraph">
<p _msttexthash="2949050" _msthash="410">Expression language operates on the following primitive data types:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="46462" _msthash="411">Type</th>
<th class="tableblock halign-left valign-top" _msttexthash="263913" _msthash="412">Attribute specs</th>
<th class="tableblock halign-left valign-top" _msttexthash="115154" _msthash="413">Literals</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="115466" _msthash="414">Integers</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>type: uX</code><font _mstmutation="1" _msttexthash="8580" _msthash="415">, , </font><code>type: sX</code><code>type: bX</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>1234</code><font _mstmutation="1" _msttexthash="13728" _msthash="416">, , , </font><code>-789</code><code>0xfc08</code><code>0b1101</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="464477" _msthash="417">Floating point numbers</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>type: fX</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>123.0</code><font _mstmutation="1" _msttexthash="8580" _msthash="418">, , </font><code>-456.78</code><code>4.1607804e+72</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="113672" _msthash="419">Booleans</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>type: b1</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code><font _mstmutation="1" _msttexthash="4004" _msthash="420">, </font><code>false</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="161382" _msthash="421">Byte arrays</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>size: XXX</code><font _mstmutation="1" _msttexthash="4004" _msthash="422">, </font><code>size-eos: true</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>[0x20, 65, 66, 67]</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="97838" _msthash="423">Strings</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>type: str</code><font _mstmutation="1" _msttexthash="4004" _msthash="424">, </font><code>type: strz</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>'foo bar'</code><font _mstmutation="1" _msttexthash="4004" _msthash="425">, </font><code>"baz\nqux"</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="62023" _msthash="426">Enums</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">(<code>type: uX</code><font _mstmutation="1" _msttexthash="70694" _msthash="427"> or ) and </font><code>type: sX</code><code>enum: XXX</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>opcode::jmp</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="96395" _msthash="428">Streams</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="19591" _msthash="429">N/A</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="19591" _msthash="430">N/A</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="9551451" _msthash="431"><strong _mstmutation="1">Integers</strong> come from , ,  type specifications in sequence
or instance attributes (i.e. , , , , etc), or can be
specified literally. One can use:</font><code>uX</code><code>sX</code><code>bX</code><code>u1</code><code>u4le</code><code>s8</code><code>b3</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="269360" _msthash="432">decimal form (e.g. </font><code>123</code>)</p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="10366720" _msthash="433">hexadecimal form using  prefix (e.g.  — both upper case and lower case letters are legal, i.e.  or  will do as well)</font><code>0x</code><code>0xcafe</code><code>0XcAfE</code><code>0xCAfe</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="637871" _msthash="434">binary form using  prefix (e.g. </font><code>0b</code><code>0b00111011</code>)</p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="593710" _msthash="435">octal form using  prefix (e.g. </font><code>0o</code><code>0o755</code>)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="16392688" _msthash="436">It’s possible to use  as a visual separator in literals — it will
be completely ignored by the parser. This could be useful, for example,
to:</font><code>_</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="1581632" _msthash="437">visually separate thousands in decimal numbers: </font><code>123_456_789</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="922454" _msthash="438">show individual bytes/words in hex: </font><code>0x1234_5678_abcd</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="677781" _msthash="439">show nibbles/bytes in binary: </font><code>0b1101_0111</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="22687964" _msthash="440"><strong _mstmutation="1">Floating point numbers</strong> also follow the normal notation used in the vast
majority of languages:  will work, as well as exponential
notation: . Use  to enforce floating point type to
an otherwise integer literal.</font><code>123.456</code><code>123.456e-55</code><code>123.0</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="53187290" _msthash="441"><strong _mstmutation="1">Booleans</strong> can be specified as literal  and  values as in
most languages, but also can be derived by using . This
method parses a single bit from a stream and represents it as a
boolean value: 0 becomes false, 1 becomes true. This is very useful to
parse flag bitfields, as you can omit  syntax and just
use something more concise, such as .</font><code>true</code><code>false</code><code>type: b1</code><code>flag_foo != 0</code><code>is_foo</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="243158539" _msthash="442"><strong _mstmutation="1">Byte arrays</strong> are defined in the attribute syntax when you don’t
specify anything as . The size of a byte array is thus determined
using ,  or , one of which is mandatory in
this case. Byte array literals use typical array syntax like the one
used in Python, Ruby and JavaScript: i.e. . There is a
little catch here: the same syntax is used for "true" arrays of
objects (see below), so if you try to do stuff like 
( obviously won’t fit in a byte), you won’t get a byte array,
you’ll get an array of integers instead.</font><code>type</code><code>size</code><code>size-eos</code><code>terminator</code><code>[1, 2, 3]</code><code>[1, 1000, 5]</code><code>1000</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="29436264" _msthash="443"><strong _mstmutation="1">Strings</strong> normally come from using  (or , which
is a shortcut that implicitly adds ).
Literal strings can be specified using double quotes or single
quotes. The meaning of single and double quotes is similar to those of
Ruby, PHP and Shell script:</font><code>type: str</code><code>type: strz</code><code>terminator: 0</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="57070884" _msthash="444">Single quoted strings are interpreted literally, i.e. backslash ,
double quotes  and other possible special symbols carry no
special meaning, they would be just considered a part of the
string. Everything between single quotes is interpreted literally,
i.e. there is no way one can include a single quote inside a single
quoted string.</font><code>\</code><code>"</code></p>
</li>
<li>
<p _msttexthash="10864282" _msthash="445">Double quoted strings support escape sequences and thus allow you to
specify any characters. The supported escape sequences are as
follows:</p>
</li>
</ul>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 16.6666%;">
<col style="width: 16.6666%;">
<col style="width: 16.6666%;">
<col style="width: 50.0002%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="134056" _msthash="446">Escape seq</th>
<th class="tableblock halign-left valign-top" _msttexthash="106873" _msthash="447">Code (dec)</th>
<th class="tableblock halign-left valign-top" _msttexthash="111319" _msthash="448">Code (hex)</th>
<th class="tableblock halign-left valign-top" _msttexthash="92742" _msthash="449">Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\a</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="5005" _msthash="450">7</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="23283" _msthash="451">0x7</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="46098" _msthash="452">bell</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\b</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="5096" _msthash="453">8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="23400" _msthash="454">0x8</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="132522" _msthash="455">backspace</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\t</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="5187" _msthash="456">9</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="23517" _msthash="457">0x9</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="236379" _msthash="458">horizontal tab</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\n</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="9451" _msthash="459">10</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="28197" _msthash="460">0xa</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="97721" _msthash="461">newline</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\v</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="9555" _msthash="462">11</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="28314" _msthash="463">0xb</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="180622" _msthash="464">vertical tab</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\f</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="9659" _msthash="465">12</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="28431" _msthash="466">0xc</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="113945" _msthash="467">form feed</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\r</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="9763" _msthash="468">13</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="28548" _msthash="469">0xd</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="266201" _msthash="470">carriage return</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\e</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="10270" _msthash="471">27</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="35321" _msthash="472">0x1b</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="77116" _msthash="473">escape</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\"</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="10049" _msthash="474">34</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="29198" _msthash="475">0x22</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="186758" _msthash="476">double quote</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\'</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="10569" _msthash="477">39</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="29848" _msthash="478">0x27</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="1979406" _msthash="479">single quote (technically not required, but supported)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\\</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="10387" _msthash="480">92</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="35919" _msthash="481">0x5c</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="135395" _msthash="482">backslash</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\123</code></p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="2659943" _msthash="483">ASCII character with octal code 123; one can specify 1..3 octal digits</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>\u12bf</code></p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="3073226" _msthash="484">Unicode character with code U+12BF; one must specify exactly 4 hex digits</p></td>
</tr>
</tbody>
</table>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="485">Note</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="18942833" _msthash="486">
One of the most widely used control characters, ASCII zero
character (code 0) can be specified as  — exactly as it works in
most languages.
</font><code>\0</code></td>
</tr>
</tbody></table>
</div>
<div class="admonitionblock caution">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="95875" _msthash="487">Caution</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="46008248" _msthash="488">
Octal notation is prone to errors: due to its flexible
length, it can swallow decimal digits that appear after the code as
part of octal specification. For example,  is three characters:
, ASCII zero, . However,  is interpreted as two
characters:  and ASCII code 2, as  is interpreted as one octal
escape sequence.
</font><code>a\0b</code><code>a</code><code>b</code><code>1\02</code><code>1</code><code>\02</code></td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="138203" _msthash="489">TODO: Enums</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="76625965" _msthash="490"><strong _mstmutation="1">Streams</strong> are internal objects that track the byte stream that we
parse and the state of parsing (i.e. where the pointer is). There is no
way to declare a stream-type attribute directly by parsing
instructions or specify it as a literal. The typical way to get stream
objects is to query the  attribute from a user-defined object: that
will give us a stream associated with this particular object.</font><code>_io</code></p>
</div>
</div>
<div class="sect2">
<h3 id="_composite_data_types" _msttexthash="513435" _msthash="491">6.2. Composite data types</h3>
<div class="paragraph">
<p _msttexthash="7917949" _msthash="492">There are two composite data types in the expression language
(i.e. data types which include other types as components).</p>
</div>
<div class="sect3">
<h4 id="_user_defined_types" _msttexthash="518778" _msthash="493">6.2.1. User-defined types</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="15179918" _msthash="494">User-defined types are the types one defines using  syntax —
i.e. the top-level structure and all substructures defined in the  key.</font><code>.ksy</code><code>types</code></p>
</div>
<div class="paragraph">
<p _msttexthash="22448517" _msthash="495">Normally, they are translated into classes (or their closest available
equivalent — i.e. a storage structure with members + access members) in the
target language.</p>
</div>
</div>
<div class="sect3">
<h4 id="_arrays" _msttexthash="163644" _msthash="496">6.2.2. Arrays</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="114475478" _msthash="497">Array types are just what one might expect from an all-purpose, generic
array type. Arrays come from either using the repetition syntax
() in an attribute specification, or by specifying a literal
array. In any case, all Kaitai Struct arrays have an underlying data type that they
store, i.e. one can’t put strings and integers into the same
array. One can do arrays based on any primitive data type or composite
data type.</font><code>repeat: …​</code></p>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="498">Note</div>
</td>
<td class="content" _msttexthash="47847540" _msthash="499">
"True" array types (described in this section) and "byte arrays"
share the same literal syntax and lots of method APIs, but they are
actually very different types. This is done on purpose, because many
target languages use very different types for byte arrays and arrays
of objects for performance reasons.
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="23105225" _msthash="500">One can use array literals syntax to declare an array (very similar to
the syntax used in JavaScript, Python and Ruby). Type will be derived
automatically based on the types of values inside brackets, for example:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>[123, 456, -789]</code><font _mstmutation="1" _msttexthash="1063946" _msthash="501"> — array of integers</font></p>
</li>
<li>
<p><code>[123.456, 1.234e+78]</code><font _mstmutation="1" _msttexthash="1003743" _msthash="502"> — array of floats</font></p>
</li>
<li>
<p><code>["foo", "bar"]</code><font _mstmutation="1" _msttexthash="1037270" _msthash="503"> — array of strings</font></p>
</li>
<li>
<p><code>[true, true, false]</code><font _mstmutation="1" _msttexthash="1060696" _msthash="504"> — array of booleans</font></p>
</li>
<li>
<p><code>[a0, a1, b0]</code><font _mstmutation="1" _msttexthash="6649071" _msthash="505"> — given that ,  and  are all the same
objects of user-defined type , this would be array of
user-defined type </font><code>a0</code><code>a1</code><code>b0</code><code>some_type</code><code>some_type</code></p>
</li>
</ul>
</div>
<div class="admonitionblock warning">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="95225" _msthash="506">Warning</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="8380307" _msthash="507">
Mixing multiple different types in a single array literal
would trigger a compile-time error, for example, this is illegal: </font><code>[1,
"foo"]</code>
</td>
</tr>
</tbody></table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_operators" _msttexthash="210886" _msthash="508">6.3. Operators</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="38288900" _msthash="509">Literals can be connected using operators to make meaningful
expressions. Operators are type-dependent: for example, the 
operator applied to two integers would mean arithmetic addition, while the same operator
applied to two strings would mean string concatenation.</font><code>+</code></p>
</div>
<div class="sect3">
<h4 id="_arithmetic_operators" _msttexthash="621153" _msthash="510">6.3.1. Arithmetic operators</h4>
<div class="paragraph">
<p _msttexthash="972608" _msthash="511">Can be applied to integers and floats:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>a + b</code><font _mstmutation="1" _msttexthash="874588" _msthash="512"> — addition</font></p>
</li>
<li>
<p><code>a - b</code><font _mstmutation="1" _msttexthash="949195" _msthash="513"> — subtraction</font></p>
</li>
<li>
<p><code>a * b</code><font _mstmutation="1" _msttexthash="1032382" _msthash="514"> — multiplication</font></p>
</li>
<li>
<p><code>a / b</code><font _mstmutation="1" _msttexthash="877669" _msthash="515"> — division</font></p>
</li>
<li>
<p><code>a % b</code><font _mstmutation="1" _msttexthash="7608588" _msthash="516"> — modulo; note that it’s not a remainder:  is ,
not ; the result is undefined for negative .</font><code>-5 % 3</code><code>1</code><code>-2</code><code>b</code></p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="517">Note</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="13834821" _msthash="518">
If both operands are integers, the result of an arithmetic operation is
an integer, otherwise it is a floating point number. For example, that
means that  is , and  is .
</font><code>7 / 2</code><code>3</code><code>7 / 2.0</code><code>3.5</code></td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="520273" _msthash="519">Can be applied to strings:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>a + b</code><font _mstmutation="1" _msttexthash="1197729" _msthash="520"> — string concatenation</font></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_relational_operators" _msttexthash="621452" _msthash="521">6.3.2. Relational operators</h4>
<div class="paragraph">
<p _msttexthash="1430689" _msthash="522">Can be applied to integers, floats and strings:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>a &lt; b</code><font _mstmutation="1" _msttexthash="1413490" _msthash="523"> — true if  is strictly less than </font><code>a</code><code>b</code></p>
</li>
<li>
<p><code>a &lt;= b</code><font _mstmutation="1" _msttexthash="1362829" _msthash="524"> — true if  is less or equal than </font><code>a</code><code>b</code></p>
</li>
<li>
<p><code>a &gt; b</code><font _mstmutation="1" _msttexthash="1546519" _msthash="525"> — true if  is strictly greater than </font><code>a</code><code>b</code></p>
</li>
<li>
<p><code>a &gt;= b</code><font _mstmutation="1" _msttexthash="1493609" _msthash="526"> — true if  is greater or equal than </font><code>a</code><code>b</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="5975645" _msthash="527">Can be applied to integers, floats, strings, booleans and enums (does
proper string value comparison):</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>a == b</code><font _mstmutation="1" _msttexthash="1066312" _msthash="528"> — true if  is equal to </font><code>a</code><code>b</code></p>
</li>
<li>
<p><code>a != b</code><font _mstmutation="1" _msttexthash="1170624" _msthash="529"> — true if  is not equal to </font><code>a</code><code>b</code></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_bitwise_operators" _msttexthash="498576" _msthash="530">6.3.3. Bitwise operators</h4>
<div class="paragraph">
<p _msttexthash="725166" _msthash="531">Can only be applied to integers.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>a &lt;&lt; b</code><font _mstmutation="1" _msttexthash="1096394" _msthash="532"> — left bitwise shift</font></p>
</li>
<li>
<p><code>a &gt;&gt; b</code><font _mstmutation="1" _msttexthash="1130909" _msthash="533"> — right bitwise shift</font></p>
</li>
<li>
<p><code>a &amp; b</code><font _mstmutation="1" _msttexthash="899990" _msthash="534"> — bitwise AND</font></p>
</li>
<li>
<p><code>a | b</code><font _mstmutation="1" _msttexthash="888524" _msthash="535"> — bitwise OR</font></p>
</li>
<li>
<p><code>a ^ b</code><font _mstmutation="1" _msttexthash="907777" _msthash="536"> — bitwise XOR</font></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_logical_boolean_operators" _msttexthash="863122" _msthash="537">6.3.4. Logical (boolean) operators</h4>
<div class="paragraph">
<p _msttexthash="970853" _msthash="538">Can be only applied to boolean values.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>not x</code><font _mstmutation="1" _msttexthash="902720" _msthash="539"> — boolean NOT</font></p>
</li>
<li>
<p><code>a and b</code><font _mstmutation="1" _msttexthash="896441" _msthash="540"> — boolean AND</font></p>
</li>
<li>
<p><code>a or b</code><font _mstmutation="1" _msttexthash="884975" _msthash="541"> — boolean OR</font></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_ternary_if_then_else_operator" _msttexthash="1046383" _msthash="542">6.3.5. Ternary (if-then-else) operator</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="4969926" _msthash="543">If  (must be boolean expression) is true, then 
value is returned, otherwise  value is returned:</font><code>condition</code><code>if_true</code><code>if_false</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-n">condition</span><span class="tok-w"> </span><span class="tok-o">?</span><span class="tok-w"> </span><span class="tok-n">if_true</span><span class="tok-w"> </span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-n">if_false</span>

<span class="tok-c1">// Examples</span>
<span class="tok-n">code</span><span class="tok-w"> </span><span class="tok-o">==</span><span class="tok-w"> </span><span class="tok-n">block_type</span><span class="tok-p">::</span><span class="tok-n">int32</span><span class="tok-w"> </span><span class="tok-o">?</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-w"> </span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-mi">8</span>
<span class="tok-s">"It has a header: "</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">has_header</span><span class="tok-w"> </span><span class="tok-o">?</span><span class="tok-w"> </span><span class="tok-s">"Yes"</span><span class="tok-w"> </span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-s">"No"</span><span class="tok-p">)</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="544">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p><code>if_true</code><font _mstmutation="1" _msttexthash="45536192" _msthash="545"> and  must have compatible types. As some
languages (for example, C++ and, to some extent, Java) do not allow
storage of, for example, strings, integers and byte arrays in the same
variable, it’s generally a bad idea to do something like  or .</font><code>if_false</code><code>foo ? 123 :
"some_string"</code><code>foo ? true : [12, 34]</code></p>
</div>
<div class="paragraph">
<p _msttexthash="441012" _msthash="546">It is acceptable to mix:</p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="11737804" _msthash="547">integers of various origins and sizes — it would result in a universal
"one size fits all" integer for a target language</p>
</li>
<li>
<p _msttexthash="6228014" _msthash="548">integers and floats — it would result in a "one size fits all"
floating point type</p>
</li>
<li>
<p _msttexthash="1174368" _msthash="549">strings of various origins and encodings</p>
</li>
<li>
<p _msttexthash="629694" _msthash="550">booleans of various origins</p>
</li>
<li>
<p _msttexthash="9195810" _msthash="551">objects of different user-defined types — it would result in a
generic KaitaiStruct object</p>
</li>
</ul>
</div>
</td>
</tr>
</tbody></table>
</div>
<div class="admonitionblock caution">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="95875" _msthash="552">Caution</div>
</td>
<td class="content">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="46410689" _msthash="553">Using the ternary operator inside a KSY file (which must remain a valid YAML
file) might be tricky, as some YAML parsers do not allow colons ()
inside strings literals. So, trying something like this would fail in
some parsers (namely, it <strong _mstmutation="1">will</strong> fail using "desktop"
kaitai-struct-compiler running under JVM):</font><code>:</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">foo</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">condition ? 4</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="2936570" _msthash="554">To ensure maximum compatibility, put quotes around such strings, i.e:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">foo</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-s">'condition</span><span class="tok-nv"> </span><span class="tok-s">?</span><span class="tok-nv"> </span><span class="tok-s">4</span><span class="tok-nv"> </span><span class="tok-s">:</span><span class="tok-nv"> </span><span class="tok-s">8'</span></code></pre>
</div>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="methods" _msttexthash="154921" _msthash="555">6.4. Methods</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="30694027" _msthash="556">Just about every value in expression language is an object (including
literals), and it’s possible to call methods on it. The common syntax
to use is , which can be abbreviated
to  if no parameters are required.</font><code>obj.method(param1, param2, …​)</code><code>obj.method</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="48102275" _msthash="557">Note that when the  in question is a user-defined type, you can
access all its attributes (both sequence and instances) using the same
 syntax. One can chain that to traverse a
chain of substructures:  (given that  is a
user-defined type that has a  field, which points to a user-defined
type that has a  field, and so on).</font><code>obj</code><code>obj.attr_name</code><code>obj.foo.bar.baz</code><code>obj</code><code>foo</code><code>bar</code></p>
</div>
<div class="paragraph">
<p _msttexthash="5467449" _msthash="558">There are a few pre-defined methods that form a kind of "standard
library" for expression language.</p>
</div>
<div class="sect3">
<h4 id="int-methods" _msttexthash="216385" _msthash="559">6.4.1. Integers</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="560">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="561">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="562">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>to_s</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="78403" _msthash="563">String</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="2533908" _msthash="564">Converts an integer into a string using decimal representation</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="float-methods" _msttexthash="667329" _msthash="565">6.4.2. Floating point numbers</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="566">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="567">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="568">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>to_i</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="569">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="1483599" _msthash="570">Truncates a floating point number to an integer</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="bytes-methods" _msttexthash="280449" _msthash="571">6.4.3. Byte arrays</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="572">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="573">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="574">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>length</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="575">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="580372" _msthash="576">Number of bytes in the array</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>to_s(encoding)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="78403" _msthash="577">String</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><font _mstmutation="1" _msttexthash="3793881" _msthash="578">Decodes (converts) a byte array encoded using the specified  scheme into a string</font><code>encoding</code></p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="str-methods" _msttexthash="192400" _msthash="579">6.4.4. Strings</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="580">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="581">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="582">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>length</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="583">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="1164904" _msthash="584">Length of a string in number of characters</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>reverse</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="78403" _msthash="585">String</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="624325" _msthash="586">Reversed version of a string</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>substring(from, to)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="78403" _msthash="587">String</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><font _mstmutation="1" _msttexthash="6147024" _msthash="588">Extracts a portion of a string between character at offset  and character at offset  (including , excluding </font><code>from</code><code>to - 1</code><code>from</code><code>to</code>)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>to_i</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="589">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="2123602" _msthash="590">Converts a string in decimal representation to an integer</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>to_i(radix)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="591">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><font _mstmutation="1" _msttexthash="10072933" _msthash="592">Converts a string with a number stored in  representation (i.e. use  to get hexadecimal representation, use  to get octal, etc) to an integer</font><code>radix</code><code>16</code><code>8</code></p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="enum-methods" _msttexthash="139100" _msthash="593">6.4.5. Enums</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="594">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="595">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="596">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>to_i</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="597">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="2631876" _msthash="598">Converts an enum into the corresponding integer representation</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="bool-methods" _msttexthash="214214" _msthash="599">6.4.6. Booleans</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="600">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="601">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="602">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>to_i</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="603">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><font _mstmutation="1" _msttexthash="1964703" _msthash="604">Returns  if the boolean value is  or  if the boolean value is </font><code>0</code><code>false</code><code>1</code><code>true</code></p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="usertype-methods" _msttexthash="519870" _msthash="605">6.4.7. User-defined types</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="54370732" _msthash="606">All user-defined types can be queried to get attributes (sequence
attributes or instances) by their name. In addition to that, there are
a few pre-defined internal methods (they all start with an underscore
, so they don’t clash with regular attribute names):</font><code>_</code></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="607">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="608">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="609">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>_root</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="312650" _msthash="610">User-defined type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="1668407" _msthash="611">Top-level user-defined structure in current file</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>_parent</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="312650" _msthash="612">User-defined type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="3110328" _msthash="613">Structure that produced this particular instance of user-defined type</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>_io</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="76960" _msthash="614">Stream</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="2006004" _msthash="615">Stream associated with this object of user-defined type</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="_array_types" _msttexthash="284440" _msthash="616">6.4.8. Array types</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="617">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="618">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="619">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>first</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="235352" _msthash="620">Array base type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="709657" _msthash="621">Gets first element of the array</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>last</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="235352" _msthash="622">Array base type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="663299" _msthash="623">Gets last element of the array</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>size</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="624">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="708591" _msthash="625">Number of elements in the array</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>min</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="235352" _msthash="626">Array base type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="953394" _msthash="627">Gets the minimum element of the array</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>max</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="235352" _msthash="628">Array base type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="953914" _msthash="629">Gets the maximum element of the array</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="_streams" _msttexthash="190814" _msthash="630">6.4.9. Streams</h4>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top" _msttexthash="154583" _msthash="631">Method name</th>
<th class="tableblock halign-left valign-top" _msttexthash="164684" _msthash="632">Return type</th>
<th class="tableblock halign-left valign-top" _msttexthash="183612" _msthash="633">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>eof</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="92742" _msthash="634">Boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code><font _mstmutation="1" _msttexthash="4543201" _msthash="635"> if we’ve reached end of the stream (no more data can be read from it),  otherwise</font><code>false</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>size</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="636">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="760786" _msthash="637">Total size of the stream in bytes</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pos</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="94536" _msthash="638">Integer</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock" _msttexthash="3130621" _msthash="639">Current position in the stream, in bytes from the beginning of the stream</p></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_advanced_techniques" _msttexthash="442312" _msthash="640">7. Advanced techniques</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="switch-advanced" _msttexthash="462449" _msthash="641">7.1. Advanced switching</h3>
<div class="sect3">
<h4 id="_switching_over_strings" _msttexthash="673348" _msthash="642">7.1.1. Switching over strings</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="172212378" _msthash="643">One can use type switching over other comparable values,
not just integers. For example, one can switch over a string value. Note
that the left side (key) of a  map is a full-featured Kaitai Struct expression,
thus all we need is to specify a string. Don’t forget that there’s
still YAML syntax that might get in a way, so we effectively need to
quote strings twice: once for Kaitai Struct expression language, and once in the
YAML representation to save these quotes from being interpreted by
a YAML parser, i.e.:</font><code>cases</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-s">'"KETCHUP"'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_1</span>
<span class="tok-w">        </span><span class="tok-s">'"MUSTARD"'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_2</span>
<span class="tok-w">        </span><span class="tok-s">'"GUACAMOLE"'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_3</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="12611248" _msthash="644">If the target language allows switching over strings, it will be rendered
as a -style statement, or, if it does not, ksc will fall back to an
-based rendition.</font><code>switch</code><code>if</code></p>
</div>
</div>
<div class="sect3">
<h4 id="_switching_over_enums" _msttexthash="581854" _msthash="645">7.1.2. Switching over enums</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="29477292" _msthash="646">One can switch over enums as well. To match against enum values, you would
have to specify enum literals (i.e. ). Since
there are colons in them, we’ll have to use YAML quotes again:</font><code>enum_name::some_value</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2</span>
<span class="tok-w">    </span><span class="tok-nt">enum</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">media</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-s">'media::cdrom'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_1</span>
<span class="tok-w">        </span><span class="tok-s">'media::dvdrom'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_2</span>
<span class="tok-w">        </span><span class="tok-s">'media::cassette'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_3</span></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_fourcc" _msttexthash="145015" _msthash="647">7.1.3. FourCC</h4>
<div class="paragraph">
<p _msttexthash="82151849" _msthash="648">Quite a few formats (like TIFF, RIFF, AVI, etc) use a
"FourCC" to switch over in a typical TLV implementation. "FourCC"
(which stands for "four character code") is essentially a 4-byte
value, which is often made human-readable to aid debugging. It’s
usually tempting to read a fixed-size string from the stream and match it against a
list of strings:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fourcc</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">4</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ASCII</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fourcc</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-s">'"RGB2"'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_rgb2</span>
<span class="tok-w">        </span><span class="tok-s">'"RLE4"'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_rle4</span>
<span class="tok-w">        </span><span class="tok-s">'"RLE8"'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_rle8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="944398" _msthash="649">However, this is generally a bad idea:</p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="49144277" _msthash="650">Reading and matching strings is slow. At least it’s much slower than
reading a single 4-byte integer (because it often involves multiple
copying of data, encoding checks / conversions, etc). The whole
point of using 4-byte FourCC originally was to provide a fast way to
read it in single operation.</p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="41684214" _msthash="651">It’s hard to provide an encoding for such a string. Quite a few
formats introduced non-ASCII FourCC values, and, even if all current
values are ASCII-safe, there’s no guarantee that there would be no
weird values like  in future.</font><code>C6 A2 ED 39</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="2791776" _msthash="652">The recommended way to handle FourCC-style types is by using an enum:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fourcc</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4le</span>
<span class="tok-w">    </span><span class="tok-nt">enum</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">pixel_formats</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fourcc</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-s">'pixel_formats::rgb2'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_rgb2</span>
<span class="tok-w">        </span><span class="tok-s">'pixel_formats::rle4'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_rle4</span>
<span class="tok-w">        </span><span class="tok-s">'pixel_formats::rle8'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_rle8</span>
<span class="tok-nt">enums</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">pixel_formats</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">0x32424752</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rgb2</span>
<span class="tok-w">    </span><span class="tok-nt">0x34454C52</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rle4</span>
<span class="tok-w">    </span><span class="tok-nt">0x38454C52</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rle8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="9549995" _msthash="653">This runs as fast as it was originally intended, and it provides an extra
benefit of allowing more verbose FourCC value descriptions.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="do-nothing" _msttexthash="206089" _msthash="654">7.2. Do nothing</h3>
<div class="paragraph">
<p _msttexthash="24783304" _msthash="655">In some rare cases, you need a type that actually does absolutely
nothing. For example, you purposely want to ignore parsing a certain
switch case and avoid running it through the default type, e.g. a situation
like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type</span>
<span class="tok-w">      </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_1</span>
<span class="tok-w">        </span><span class="tok-nt">2</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_2</span>
<span class="tok-w">        </span><span class="tok-nt">3</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">dummy</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= must ignore rec_type=3!</span>
<span class="tok-w">        </span><span class="tok-nt">_</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">rec_type_others</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="5851690" _msthash="656">This is very easy to achieve. Here are a few examples of type
definitions which do nothing when invoked:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-c1"># One can use empty JSON object syntax to avoid specifying any of</span>
<span class="tok-w">  </span><span class="tok-c1"># `seq`, `instances`, etc, sections.</span>
<span class="tok-w">  </span><span class="tok-nt">dummy_1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">{}</span>
<span class="tok-w">  </span><span class="tok-c1"># One can use explicit doc to note that there's nothing there.</span>
<span class="tok-w">  </span><span class="tok-nt">dummy_2</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">doc</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">This type is intentionally left blank.</span>
<span class="tok-w">  </span><span class="tok-c1"># One can use empty `seq` or `instances` or `types` section, any</span>
<span class="tok-w">  </span><span class="tok-c1"># other empty sections, or any combination of thereof.</span>
<span class="tok-w">  </span><span class="tok-nt">dummy_3</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">[]</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">{}</span>
<span class="tok-w">    </span><span class="tok-nt">types</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-p tok-p-Indicator">{}</span>
<span class="tok-w">  </span><span class="tok-c1"># One can use a very explicit notion of the fact that we want to parse 0 bytes.</span>
<span class="tok-w">  </span><span class="tok-nt">dummy_4</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">no_value</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="delimited-struct-advanced" _msttexthash="929071" _msthash="657">7.3. Advanced delimited structures</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="44413148" _msthash="658"><a href="https://doc.kaitai.io/user_guide.html#delimited-struct" _mstmutation="1">Delimited structures</a>, having 
specified to define a structure of arbitrary size, are pretty common
and useful. However, sometimes you’re dealing with more advanced
versions of these which require you to fine-tune certain aspects of
delimiting.</font><code>terminator</code></p>
</div>
<div class="sect3">
<h4 id="consume-include" _msttexthash="1035346" _msthash="659">7.3.1. Terminator: consume or include?</h4>
<div class="paragraph">
<p _msttexthash="100023703" _msthash="660">What happens with the terminator byte itself, when you’re defining a
delimited structure? Normally, terminator is not needed inside your
structure, it’s an external entity. For example, if you’re parsing
dot-delimited strings, you don’t want these strings to contain the
dot:</p>
</div>
<table class="tableblock frame-none grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="title" _msttexthash="25870" _msthash="661">KSY</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x2e</span><span class="tok-w"> </span><span class="tok-c1"># `.`</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str2</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x2e</span><span class="tok-w"> </span><span class="tok-c1"># `.`</span></code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="literalblock">
<div class="title" _msttexthash="271791" _msthash="662">Input and output</div>
<div class="content">
<pre>66 6f 6f 2e 62 61 72 2e = "foo.bar."

str1 = "foo"
str2 = "bar"</pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="8789118" _msthash="663">But sometimes you indeed want that dot, and it should be part of the
output. This is possible by specifying 
(the default is false):</font><code>include: true</code></p>
</div>
<table class="tableblock frame-none grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="title" _msttexthash="25870" _msthash="664">KSY</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x2e</span><span class="tok-w"> </span><span class="tok-c1"># `.`</span>
<span class="tok-w">    </span><span class="tok-nt">include</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">true</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str2</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x2e</span><span class="tok-w"> </span><span class="tok-c1"># `.`</span>
<span class="tok-w">    </span><span class="tok-nt">include</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">true</span></code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="literalblock">
<div class="title" _msttexthash="271791" _msthash="665">Input and output</div>
<div class="content">
<pre>66 6f 6f 2e 62 61 72 2e = "foo.bar."

str1 = "foo."
str2 = "bar."</pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="43699773" _msthash="666">Or sometimes your terminator is actually part of a following structure,
and you don’t want it to be consumed — you want the next structure to
start with that terminator byte. This is possible with
 (which is true by default):</font><code>consume: false</code></p>
</div>
<table class="tableblock frame-none grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="listingblock">
<div class="title" _msttexthash="25870" _msthash="667">KSY</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x2e</span><span class="tok-w"> </span><span class="tok-c1"># `.`</span>
<span class="tok-w">    </span><span class="tok-nt">consume</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">false</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">the_rest</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">size-eos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">true</span></code></pre>
</div>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="literalblock">
<div class="title" _msttexthash="271791" _msthash="668">Input and output</div>
<div class="content">
<pre>66 6f 6f 2e 62 61 72 2e = "foo.bar."

str1 = "foo"
the_rest = ".bar."</pre>
</div>
</div></div></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="eos-error" _msttexthash="1523158" _msthash="669">7.3.2. Ignoring errors in delimited structures</h4>
<div class="paragraph">
<p _msttexthash="53119131" _msthash="670">Delimited structures actually can be pretty scary: if we read until
the terminator is encountered, what will happen if we never find
one? In raw C, a typical answer is a "segmentation fault" occurring in
the operation that deals with such strings due to runaway reads past
the buffer, i.e. a very bad thing and a big security hole.</p>
</div>
<div class="paragraph">
<p _msttexthash="43832087" _msthash="671">In Kaitai Struct, however, you can control this behavior. By default,
if you parse a structure awaiting a terminator, and that
terminator never happens, you’ll get a clear error / exception similar
to "attempted to read past end of stream".</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="15681367" _msthash="672">In some cases, you
really want to read until the end of the stream, and this should be
considered normal encoding, not an error. For these cases, you can
specify  (the default is ):</font><code>eos-error: false</code><code>true</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_string</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">    </span><span class="tok-nt">terminator</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0</span>
<span class="tok-w">    </span><span class="tok-nt">eos-error</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">false</span>
<span class="tok-w">    </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">UTF-8</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="7368946" _msthash="673">This structure will read both terminated and non-terminated strings
successfully, without triggering an error:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>61 62 63 00 64 65 66 =&gt; my_string = "abc"
61 62 63 00          =&gt; my_string = "abc"
61 62 63             =&gt; my_string = "abc"</pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="meta-imports" _msttexthash="989508" _msthash="674">7.4. Importing types from other files</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="52633100" _msthash="675">As your project grows in complexity, you might want to have multiple
.ksy files: for example, for different file formats, structures,
substructures, or to reuse the same subformat in several places. As in most
programming languages, Kaitai Struct allows you to have multiple
source files and has  functionality for that.</font><code>imports</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="5566028" _msthash="676">Using multiple files is very easy. For example, if you have a
 file that describes the date structure:</font><code>date.ksy</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">date</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">year</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2le</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">month</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2le</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">day</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2le</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="9174594" _msthash="677">and you want to use it in a file listing specification
, here’s how to do that:</font><code>filelist.ksy</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">filelist</span>
<span class="tok-w">  </span><span class="tok-c1"># this will import "date.ksy"</span>
<span class="tok-w">  </span><span class="tok-nt">imports</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">date</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entries</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">entry</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">eos</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">entry</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">filename</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">        </span><span class="tok-nt">encoding</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ASCII</span>
<span class="tok-w">      </span><span class="tok-c1"># just use "date" type from date.ksy as if it was declared in</span>
<span class="tok-w">      </span><span class="tok-c1"># current file</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">timestamp</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">date</span>
<span class="tok-w">      </span><span class="tok-c1"># you can access its members too!</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">historical_data</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">160</span>
<span class="tok-w">        </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">timestamp.year &lt; 1970</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="6448650" _msthash="678">Generally, you just add an array in  and list all you
want to import there. There are 2 ways to address the files:</font><code>meta/imports</code></p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1" _msttexthash="114504" _msthash="679">Relative</dt>
<dd>
<p><font _mstmutation="1" _msttexthash="28950298" _msthash="680">Uses a path given as a relative path to the file, starting with the same
directory in which the main .ksy file resides. This is useful to include files in
the same directory or to navigate to somewhere in your
project. Examples include: , , , etc.</font><code>foo</code><code>foo/bar</code><code>../foo/bar/baz</code></p>
</dd>
<dt class="hdlist1" _msttexthash="115674" _msthash="681">Absolute</dt>
<dd>
<p><font _mstmutation="1" _msttexthash="34009235" _msthash="682">Looks like  or  (i.e. starting with a slash), and
searches for the given .ksy file in module search path(s). This is
usually used for modules from centralized repositories / ksy
libraries. Module search paths are determined by (in order of
decreasing priority):</font><code>/foo</code><code>/foo/bar</code></p>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="1229072" _msthash="683">Paths given using the command-line  switch.</font><code>-I</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="8170019" _msthash="684">Paths given using a  environment variable (multiple paths
can be specified separated with  on Linux/OS X and with  on
Windows)</font><code>KSPATH</code><code>:</code><code>;</code></p>
</li>
<li>
<p _msttexthash="6342674" _msthash="685">Default platform-dependent search paths, determined at compiler
build time and/or during installation</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="686">Note</div>
</td>
<td class="content" _msttexthash="20956208" _msthash="687">
In the Web IDE you obviously don’t have environment variables and command-line
  switches, so absolute path imports are used to reference modules in the
  preloaded "kaitai.io" library.
</td>
</tr>
</tbody></table>
</div>
<div class="admonitionblock caution">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="95875" _msthash="688">Caution</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="14952366" _msthash="689">
Please use only forward slashes  in import paths for
consistency. Kaitai Struct will convert them automatically to the proper
platform-dependent path separator ( or ).
</font><code>/</code><code>/</code><code>\</code></td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="opaque-types" _msttexthash="1309464" _msthash="690">7.5. Opaque types: plugging in external code</h3>
<div class="paragraph">
<p _msttexthash="27691976" _msthash="691">Sometimes you want Kaitai Struct-generated code to call code in your
application to do the parsing, for example, to parse some text- or
state-based format. For that, you can instruct ksc to generate code
with so-called "opaque" types.</p>
</div>
<div class="paragraph">
<p _msttexthash="9934015" _msthash="692">Normally, if the compiler encounters a type which is not declared either
in the current file or in one of the imported files, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">doc_container</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">doc</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">custom_encrypted_object</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="557505" _msthash="693">... it will output an error:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>/seq/0: unable to find type 'custom_encrypted_object', searching from doc_container</pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="33287605" _msthash="694">If we want to provide our own implementation of a
 type, first we need to compile our .ksy file
with the  option. This will avoid the error, and the
compiler will consider all unknown types to be "opaque", i.e. it will treat
them as existing in some external space.</font><code>custom_encrypted_object</code><code>--opaque-types=true</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="13511953" _msthash="695">Alternatively, instead of specifying the command line argument
 to the compiler, as of Kaitai Struct version 0.7,
it is now possible to specify  field  as follows:</font><code>--opaque-types=true</code><code>meta</code><code>ks-opaque-types</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">doc_container</span>
<span class="tok-w">  </span><span class="tok-nt">ks-opaque-types</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">true</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">doc</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">custom_encrypted_object</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="696">Note</div>
</td>
<td class="content" _msttexthash="15368964" _msthash="697">
Of course, the compiler doesn’t know anything about opaque types, so
trying to access any attributes of it (i.e. using expression language)
will fail.
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="2158689" _msthash="698">This will generate the following code (for example, in Java):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kd">class</span> <span class="tok-nc">DocContainer</span><span class="tok-w"> </span><span class="tok-kd">extends</span><span class="tok-w"> </span><span class="tok-n">KaitaiStruct</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-c1">// ...</span>
<span class="tok-w">    </span><span class="tok-kd">private</span><span class="tok-w"> </span><span class="tok-kt">void</span><span class="tok-w"> </span><span class="tok-nf">_read</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">        </span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">doc</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">CustomEncryptedObject</span><span class="tok-p">(</span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_io</span><span class="tok-p">);</span>
<span class="tok-w">    </span><span class="tok-p">}</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="68567213" _msthash="699">As you see,  is instantiated here with a single
argument: an IO stream. All that’s left is to create a class with a
compatible constructor that will allow a call with a single
argument. For statically typed languages, note that the constructor’s
argument is of type KaitaiStream.</font><code>CustomEncryptedObject</code></p>
</div>
<div class="paragraph">
<p _msttexthash="939341" _msthash="700">An example of what can be done (in Java):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kd">class</span> <span class="tok-nc">CustomEncryptedObject</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-kt">byte</span><span class="tok-o">[]</span><span class="tok-w"> </span><span class="tok-n">buf</span><span class="tok-p">;</span>

<span class="tok-w">    </span><span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-nf">CustomEncryptedObject</span><span class="tok-p">(</span><span class="tok-n">KaitaiStream</span><span class="tok-w"> </span><span class="tok-n">io</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">        </span><span class="tok-c1">// read all remaining bytes into our buffer</span>
<span class="tok-w">        </span><span class="tok-n">buf</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">io</span><span class="tok-p">.</span><span class="tok-na">readBytesFull</span><span class="tok-p">();</span>

<span class="tok-w">        </span><span class="tok-c1">// implement our custom super Caesar's cipher</span>
<span class="tok-w">        </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-kt">int</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-o">&lt;</span><span class="tok-w"> </span><span class="tok-n">buf</span><span class="tok-p">.</span><span class="tok-na">length</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-o">++</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">            </span><span class="tok-kt">byte</span><span class="tok-w"> </span><span class="tok-n">b</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">buf</span><span class="tok-o">[</span><span class="tok-n">i</span><span class="tok-o">]</span><span class="tok-p">;</span>
<span class="tok-w">            </span><span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">b</span><span class="tok-w"> </span><span class="tok-o">&gt;=</span><span class="tok-w"> </span><span class="tok-sc">'A'</span><span class="tok-w"> </span><span class="tok-o">&amp;&amp;</span><span class="tok-w"> </span><span class="tok-n">b</span><span class="tok-w"> </span><span class="tok-o">&lt;=</span><span class="tok-w"> </span><span class="tok-sc">'Z'</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">                </span><span class="tok-kt">int</span><span class="tok-w"> </span><span class="tok-n">letter</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">b</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-w"> </span><span class="tok-sc">'A'</span><span class="tok-p">;</span>
<span class="tok-w">                </span><span class="tok-n">letter</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">letter</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-mi">7</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">%</span><span class="tok-w"> </span><span class="tok-mi">26</span><span class="tok-p">;</span>
<span class="tok-w">                </span><span class="tok-n">buf</span><span class="tok-o">[</span><span class="tok-n">i</span><span class="tok-o">]</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-kt">byte</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">letter</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-sc">'A'</span><span class="tok-p">);</span>
<span class="tok-w">            </span><span class="tok-p">}</span>
<span class="tok-w">        </span><span class="tok-p">}</span>
<span class="tok-w">    </span><span class="tok-p">}</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="31668" _msthash="701">Tip</div>
</td>
<td class="content" _msttexthash="97240169" _msthash="702">
Alternatively, opaque types can be (ab)used to connect several
Kaitai Struct-generated types together without importing. If one type
instantiates another, but does not use it in any other way (i.e. doesn’t
access its inner attributes using expression language), one can just
compile two .ksy files separately, throw them into the same project
and they shall use each other without a problem.
</td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="custom-process" _msttexthash="789542" _msthash="703">7.6. Custom processing routines</h3>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="138944" _msthash="704">Important</div>
</td>
<td class="content" _msttexthash="604513" _msthash="705">
Feature available since v0.8.
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="66128465" _msthash="706">As discussed in <a href="https://doc.kaitai.io/user_guide.html#process" _mstmutation="1">Processing: dealing with compressed, obfuscated and encrypted data</a>, Kaitai Struct utilizes the  key to
invoke processing of the data for the purposes of "bytes in - bytes
out" transformations. It is meant to be used to implement compression &amp;
decompression, encryption &amp; decryption, obfuscation &amp; de-obfuscation,
those kind of transformations.</font><code>process</code></p>
</div>
<div class="paragraph">
<p _msttexthash="382039528" _msthash="707">Kaitai Struct runtime libraries come bundled with a "standard" set of
such transformations, but quite often one encounters the need to
implement some custom data transformation algorithm. There are many
thousands of encryption and compression algorithms. It’s impractical
to both try to implement them in declarative form using standard
Kaitai Struct types (because as an end-user, you’re most likely
interested in the decoded result, not internal structures of the
algorithm/cipher), and it’s next to impossible to bundle all the data
processing algorithms in the world into Kaitai Struct runtime (not
only it would become <strong>very</strong> bloated, but also quite a few such
algorithms are encumbered by software patents and licensing
restrictions).</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="29977870" _msthash="708">To alleviate this problem, Kaitai Struct allows one to invoke custom
processing algorithms, implemented in imperative code in target
languages. This works very similar to <a href="https://doc.kaitai.io/user_guide.html#opaque-types" _mstmutation="1">opaque external
types</a>, but for  invocations, not for 
invocations.</font><code>process</code><code>type</code></p>
</div>
<div class="paragraph">
<p _msttexthash="996060" _msthash="709">Calling a custom process type is easy:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">key</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">s4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">buf</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">50</span>
<span class="tok-w">    </span><span class="tok-nt">process</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_custom_processor(key)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="6757296" _msthash="710">This would generate something like this (example is for Java, other
target languages a use similar technique):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-c1">// Reads 50 bytes to process.</span>
<span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_raw_buf</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_io</span><span class="tok-p">.</span><span class="tok-na">readBytes</span><span class="tok-p">(</span><span class="tok-mi">50</span><span class="tok-p">);</span>

<span class="tok-c1">// Initializes processor object, passing every argument specified in</span>
<span class="tok-c1">// `process` key into constructor</span>
<span class="tok-n">MyCustomProcessor</span><span class="tok-w"> </span><span class="tok-n">_process__raw_buf</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">MyCustomProcessor</span><span class="tok-p">(</span><span class="tok-n">key</span><span class="tok-p">());</span>

<span class="tok-c1">// Invokes `decode(...)` method, passing unprocessed byte array,</span>
<span class="tok-c1">// expecting it to return a processed one.</span>
<span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">buf</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">_process__raw_buf</span><span class="tok-p">.</span><span class="tok-na">decode</span><span class="tok-p">(</span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_raw_buf</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="14643746" _msthash="711">A typical implementation of a custom processor would look like this
(again, example in Java; refer to language-specific notes for
documentation on other languages):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-kn">import</span><span class="tok-w"> </span><span class="tok-nn">io.kaitai.struct.CustomDecoder</span><span class="tok-p">;</span>

<span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kd">class</span> <span class="tok-nc">MyCustomProcessor</span><span class="tok-w"> </span><span class="tok-kd">implements</span><span class="tok-w"> </span><span class="tok-n">CustomDecoder</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-kd">private</span><span class="tok-w"> </span><span class="tok-kt">int</span><span class="tok-w"> </span><span class="tok-n">key</span><span class="tok-p">;</span>

<span class="tok-w">    </span><span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-nf">CustomFx</span><span class="tok-p">(</span><span class="tok-kt">int</span><span class="tok-w"> </span><span class="tok-n">key</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">        </span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">key</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">key</span><span class="tok-p">;</span>
<span class="tok-w">    </span><span class="tok-p">}</span>

<span class="tok-w">    </span><span class="tok-nd">@Override</span>
<span class="tok-w">    </span><span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kt">byte</span><span class="tok-o">[]</span><span class="tok-w"> </span><span class="tok-nf">decode</span><span class="tok-p">(</span><span class="tok-kt">byte</span><span class="tok-o">[]</span><span class="tok-w"> </span><span class="tok-n">src</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">        </span><span class="tok-c1">// custom "bytes in -&gt; bytes out" processing routine</span>
<span class="tok-w">        </span><span class="tok-kt">byte</span><span class="tok-o">[]</span><span class="tok-w"> </span><span class="tok-n">dst</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-kt">byte</span><span class="tok-o">[</span><span class="tok-n">src</span><span class="tok-p">.</span><span class="tok-na">length</span><span class="tok-o">]</span><span class="tok-p">;</span>
<span class="tok-w">        </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-kt">int</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-o">&lt;</span><span class="tok-w"> </span><span class="tok-n">src</span><span class="tok-p">.</span><span class="tok-na">length</span><span class="tok-p">;</span><span class="tok-w"> </span><span class="tok-n">i</span><span class="tok-o">++</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">           </span><span class="tok-n">dst</span><span class="tok-o">[</span><span class="tok-n">i</span><span class="tok-o">]</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-kt">byte</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-n">src</span><span class="tok-o">[</span><span class="tok-n">i</span><span class="tok-o">]</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">key</span><span class="tok-p">);</span>
<span class="tok-w">        </span><span class="tok-p">}</span>

<span class="tok-w">        </span><span class="tok-k">return</span><span class="tok-w"> </span><span class="tok-n">dst</span><span class="tok-p">;</span>
<span class="tok-w">    </span><span class="tok-p">}</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="45460181" _msthash="712">This example is mostly self-explanatory. Strongly typed languages, such
as Java, usually provide some sort of interface that such a custom
processor class should implement. For Java, it’s named
. And, as outlined there, we implement:</font><code>CustomDecoder</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p _msttexthash="5414838" _msthash="713">a custom constructor, which accepts the encoding parameters (like
keys, etc), as specified in a ksy</p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="12822992" _msthash="714">a  method which decodes a given byte array — in
this particular example, it just adds whatever we supplied as "key"
to every byte</font><code>decode(byte[] src)</code></p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="715">Note</div>
</td>
<td class="content">
<code>decode</code><font _mstmutation="1" _msttexthash="7231705" _msthash="716"> can return a different number of bytes than it is
given. This is perfectly normal, for example, with decompression.
</font></td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="35060506" _msthash="717">By default, specifying a plain name invokes a custom processing class
in the same namespace/package where the code is generated. If you want
to keep your generated code in a separate namespace/package than your
custom hand-made code, you can specify it like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">buf</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">50</span>
<span class="tok-w">    </span><span class="tok-nt">process</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">com.example.my_rle(5, 3)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="11530545" _msthash="718">For Java, this would result in an invocation of 
class. Other languages use similar rules of translation; see
language-specific notes for details.</font><code>com.example.MyRle</code></p>
</div>
<div class="paragraph">
<p _msttexthash="74639344" _msthash="719">A special namespace prefix "kaitai." is reserved for extended
libraries provided by the Kaitai project. As of 0.8, none of these have been
published, but in future you can expect implementations like
"kaitai.crypto.aes" or "kaitai.compress.lzma" to be provided by
libraries implemented in multiple languages that would be released
along with the minimal core Kaitai Struct runtime.</p>
</div>
</div>
<div class="sect2">
<h3 id="_enforcing_parent_type" _msttexthash="554827" _msthash="720">7.7. Enforcing parent type</h3>
<div class="paragraph">
<p _msttexthash="19338787" _msthash="721">Every object (except for the top-level object) in a .ksy file has a
parent, and that parent has a type, which is some sort of user-defined
type. What happens if two or more objects use the same type?</p>
</div>
<div class="imageblock right">
<div class="content">
<img src="./Kaitai Struct 用户指南_files/two_parents.svg" alt="two parents" _mstalt="165763" _msthash="722">
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">opcode_jmp</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">target</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">arg</span>
<span class="tok-w">  </span><span class="tok-nt">opcode_push</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">value</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">arg</span>
<span class="tok-w">  </span><span class="tok-nt">arg</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">arg_type</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">arg_value</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="96023044" _msthash="723">In this example, both opcodes use same type . Given that these
are different types, Kaitai Struct infers that the only thing they have in common
is that they are objects generated by Kaitai Struct, and thus they
usually implement KaitaiStruct API, so the best common type that will
be ok for both parents is . Here’s how it looks in any
statically-typed language, e.g. in Java:</font><code>arg</code><code>KaitaiStruct</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><span></span><span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kd">static</span><span class="tok-w"> </span><span class="tok-kd">class</span> <span class="tok-nc">OpcodeJmp</span><span class="tok-w"> </span><span class="tok-kd">extends</span><span class="tok-w"> </span><span class="tok-n">KaitaiStruct</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-c1">// ...</span>
<span class="tok-w">    </span><span class="tok-kd">private</span><span class="tok-w"> </span><span class="tok-kt">void</span><span class="tok-w"> </span><span class="tok-nf">_read</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">        </span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">target</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">Arg</span><span class="tok-p">(</span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_io</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">_root</span><span class="tok-p">);</span>
<span class="tok-w">    </span><span class="tok-p">}</span>
<span class="tok-w">    </span><span class="tok-c1">// ...</span>
<span class="tok-p">}</span>
<span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kd">static</span><span class="tok-w"> </span><span class="tok-kd">class</span> <span class="tok-nc">OpcodePush</span><span class="tok-w"> </span><span class="tok-kd">extends</span><span class="tok-w"> </span><span class="tok-n">KaitaiStruct</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-c1">// ...</span>
<span class="tok-w">    </span><span class="tok-kd">private</span><span class="tok-w"> </span><span class="tok-kt">void</span><span class="tok-w"> </span><span class="tok-nf">_read</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">        </span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">value</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">new</span><span class="tok-w"> </span><span class="tok-n">Arg</span><span class="tok-p">(</span><span class="tok-k">this</span><span class="tok-p">.</span><span class="tok-na">_io</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-k">this</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">_root</span><span class="tok-p">);</span>
<span class="tok-w">    </span><span class="tok-p">}</span>
<span class="tok-w">    </span><span class="tok-c1">// ...</span>
<span class="tok-p">}</span>
<span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-kd">static</span><span class="tok-w"> </span><span class="tok-kd">class</span> <span class="tok-nc">Arg</span><span class="tok-w"> </span><span class="tok-kd">extends</span><span class="tok-w"> </span><span class="tok-n">KaitaiStruct</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w">    </span><span class="tok-kd">public</span><span class="tok-w"> </span><span class="tok-nf">Arg</span><span class="tok-p">(</span><span class="tok-n">KaitaiStream</span><span class="tok-w"> </span><span class="tok-n">_io</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">KaitaiStruct</span><span class="tok-w"> </span><span class="tok-n">_parent</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">TopLevelClass</span><span class="tok-w"> </span><span class="tok-n">_root</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="12403677" _msthash="724">Note that both  and  supply  as 
argument in  constructor, and, as it is declared as
. As both opcode classes are declared with , this code will compile properly.</font><code>OpcodeJmp</code><code>OpcodePush</code><code>this</code><code>_parent</code><code>Arg</code><code>KaitaiStruct</code><code>extends
KaitaiStruct</code></p>
</div>
<div class="sect3">
<h4 id="_replacing_parent" _msttexthash="447512" _msthash="725">7.7.1. Replacing parent</h4>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="37618308" _msthash="726">In some situations, you might want to replace the default 
passed as  with something else. In some situations this will
provide you a clean and elegant solution to relatively complex
problems. Consider the following data structure that loosely
represents a binary tree:</font><code>this</code><code>_parent</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">tree</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">chunk_size</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">root_node</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">node</span>
<span class="tok-w">  </span><span class="tok-nt">node</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">chunk</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">???</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= need to reference chunk_size from tree type here</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_left_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_right_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">left_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">node</span>
<span class="tok-w">        </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_left_child != 0</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">right_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">node</span>
<span class="tok-w">        </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_right_child != 0</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="48572875" _msthash="727">Everything is pretty simple here. The main  type has 
and a , which is of  type. Each individual  of
this tree carries a chunk of information (of a size determined in the 
type), some flags ( and ) and then
calls itself again to parse either left or right child nodes for the
current node if they exist, according to the flags.</font><code>tree</code><code>chunk_size</code><code>root_node</code><code>node</code><code>node</code><code>tree</code><code>has_left_child</code><code>has_right_child</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="130606866" _msthash="728">The only problem is how to access  in each node. You can’t
access the tree object starting from  here, as there could be many
different trees in our file, and you need to access the current one. Using
 directly is just impossible. True, given that  type is
used both by  and  itself, it got two different parents,
so Kaitai Struct compiler downgrades node’s parent type to
KaitaiStruct, thus trying to access  would result
in a compile-time error.</font><code>chunk_size</code><code>_root</code><code>_parent</code><code>node</code><code>tree</code><code>node</code><code>_parent.chunk_size</code></p>
</div>
<div class="paragraph">
<p _msttexthash="646958" _msthash="729">TODO: add more about the error</p>
</div>
<div class="paragraph">
<p _msttexthash="4993612" _msthash="730">This situation can be resolved easily by using parent overriding. We
modify our code this way:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">tree</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">chunk_size</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">root_node</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">node</span>
<span class="tok-w">  </span><span class="tok-nt">node</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">chunk</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_parent.chunk_size</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= now one can access `tree` with _parent</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_left_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_right_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">left_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">node</span>
<span class="tok-w">        </span><span class="tok-nt">parent</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_parent</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= override parent to be be parent's parent</span>
<span class="tok-w">        </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_left_child != 0</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">right_child</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">node</span>
<span class="tok-w">        </span><span class="tok-nt">parent</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_parent</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= override parent here too</span>
<span class="tok-w">        </span><span class="tok-nt">if</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">has_right_child != 0</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="155753013" _msthash="731">We’ve changed only three lines. We’ve enforced the parent of the node in the
 and  attributes to be passed as ,
not . This, effectively, continues passing a reference to the original
node’s parent, which is a  type object, over and over in the whole
recursive structure. This way one can access the structure’s root by just
using . Naturally, we’ve done exactly that to get ourselves
 by just using .</font><code>left_child</code><code>right_child</code><code>_parent</code><code>this</code><code>tree</code><code>_parent</code><code>chunk_size</code><code>size: _parent.chunk_size</code></p>
</div>
</div>
<div class="sect3">
<h4 id="_omitting_parent" _msttexthash="417352" _msthash="732">7.7.2. Omitting parent</h4>
<div class="paragraph">
<p _msttexthash="81371030" _msthash="733">In some cases, you want some object to have no parent
at all. The primary use case for this is to make sure that some
instantiation of it does not affect the parent type. In many cases, resorting
to this method is a sign that you need to stop and rethink your
design, but for some formats, it’s unavoidable and in fact simplifies
things a lot.</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="3223285" _msthash="734">To omit parent (i.e. pass a  reference or something similar as a
parent), use .</font><code>null</code><code>parent: false</code></p>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="45344" _msthash="735">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="4809649" _msthash="736">Language design explanation: while it might seem logical to specify
, there are two catches:</font><code>parent: null</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="106267226" _msthash="737">KSY is a YAML-based language, and YAML treats  as
literally a null value, i.e. totally the same as . So, just
to allow passing solitary  as a value, you’d need to wrap
it into quotes: . This would be very awkward for
beginners, as we can’t even generate a good error message here, as
we can’t distinguish these two.</font><code>parent: null</code><code>parent:</code><code>null</code><code>parent: 'null'</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="28826707" _msthash="738">Omitting parent is actually a special case, not just a matter of
passing . In fact, some languages do not have a concept of
null, or do not allow passing null as an object reference, so we
need to treat it distinctly anyway, and emphasize that.</font><code>null</code></p>
</li>
</ul>
</div>
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="1963585" _msthash="739">TODO: an example where omitting the parent comes useful</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="typecast" _msttexthash="265213" _msthash="740">7.8. Typecasting</h3>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="138944" _msthash="741">Important</div>
</td>
<td class="content" _msttexthash="604110" _msthash="742">
Feature available since v0.7.
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="30591743" _msthash="743">Kaitai Struct always tries its best to infer all the types
automatically, but in some cases it would be impossible to do so in
compile-time. For example, there could be some extra conditions known
to the format developer, but not to Kaitai Struct.</p>
</div>
<div class="paragraph">
<p _msttexthash="21886436" _msthash="744">Consider this example — a typical image format, implemented as
<a href="https://doc.kaitai.io/user_guide.html#tlv">Typical TLV implementation (switching types on an expression)</a>, which includes a variable number of self-describing sections:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_sections</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sections</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">section</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_sections</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">section</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sect_type</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">          </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sect_type</span>
<span class="tok-w">          </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">            </span><span class="tok-nt">1</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sect_header</span>
<span class="tok-w">            </span><span class="tok-nt">2</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sect_color_data</span>
<span class="tok-w">            </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-nt">sect_header</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">width</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">height</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="31826236" _msthash="745">After that, a bitmap follows, and its size is to be derived as , as described in the  section. In addition to that,
we’re 100% sure (due to format constraints) that the body of 
is always . How do we access  and  in it?</font><code>width
* height</code><code>sect_header</code><code>sections[7]</code><code>sect_header</code><code>width</code><code>height</code></p>
</div>
<div class="paragraph">
<p _msttexthash="4547972" _msthash="746">A naïve solution like this won’t compile:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">bitmap</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sections[7].body.width * sections[7].body.height</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="744848" _msthash="747">reporting the following error:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>/seq/2/size: don't know how to call anything on AnyType</pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="160412434" _msthash="748">The reason for that is that from the root type perspective, all section
bodies are alike, and in a strongly typed language, it’s impossible to
guarantee that  would be the type we want, and that
type would have  and  attributes. Not only that, but
actually, given that we’ve specified a  attribute, a  could
be just a raw byte array, and not even a user type. Thus, Kaitai Struct decided
that it could be  — a type that can include anything.</font><code>sections[7].body</code><code>width</code><code>height</code><code>size</code><code>body</code><code>AnyType</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="6777771" _msthash="749">The best solution would be to enforce our knowledge using an explicit
typecast with the  expression operator:</font><code>.as&lt;…​&gt;</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">bitmap</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sections[7].body.as&lt;sect_header&gt;.width * sections[7].body.as&lt;sect_header&gt;.height</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2538783" _msthash="750">To make it prettier, one can extract
 using a named value instance:</font><code>sections[7].body.as&lt;sect_header&gt;</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">bitmap</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">header.width * header.height</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">header</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">sections[7].body.as&lt;sect_header&gt;</span></code></pre>
</div>
</div>
<div class="admonitionblock caution">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="95875" _msthash="751">Caution</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="71710860" _msthash="752">
Of course, if our assumption about  doesn’t come
true in run time, things will go bad. You can expect most languages to
throw a typecasting exception on a failed casting attempt, but in very
low-level languages, such as C++ with RTTI disabled, this would result
in data accessed using wrong offsets, and that could potentially lead
to a crash / segfault / security problem.
</font><code>sections[7]</code></td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="calc-endian" _msttexthash="911222" _msthash="753">7.9. Calculated default endianness</h3>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="138944" _msthash="754">Important</div>
</td>
<td class="content" _msttexthash="604513" _msthash="755">
Feature available since v0.8.
</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="73062002" _msthash="756">Most formats (like <a href="https://formats.kaitai.io/zip/">zip</a>,
<a href="https://formats.kaitai.io/gif/">gif</a>, and many others) stick to a single
fixed endianness: they always use either big-endian or little-endian
integers. Usually this stems from the architecture where the format was
developed: the format is relatively easy and quick to parse on
its "native" architecture, but requires some extra operations (and
parsing time) on non-native architectures.</p>
</div>
<div class="paragraph">
<p _msttexthash="28696785" _msthash="757">Some formats (like <a href="https://formats.kaitai.io/elf/">ELF</a> or
<a href="https://formats.kaitai.io/mach_o/">Mach-O</a>), however, take an alternative
approach: they come in two versions, with big-endian integers and
little-endian integers, and they add some sort of header field that
helps to distinguish between the two.</p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="101540036" _msthash="758">To help in implementing such formats, Kaitai Struct supports the concept of
calculated endianness. Instead of using  or ,
one can use a switch, similar to the one introduced in
<a href="https://doc.kaitai.io/user_guide.html#tlv" _mstmutation="1">Typical TLV implementation (switching types on an expression)</a>. Consider this example of a TIFF file — it begins with either
"II" (0x49, 0x49) to specify little-endian encoding or "MM" (0x4d,
0x4d) to specify big-endian encoding:</font><code>endian: be</code><code>endian: le</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">tiff</span>
<span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">indicator</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">2</span><span class="tok-w"> </span><span class="tok-c1"># first two bytes determines endianness</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">tiff_body</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">tiff_body</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">endian</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_root.indicator</span>
<span class="tok-w">        </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">          </span><span class="tok-s">'[0x49,</span><span class="tok-nv"> </span><span class="tok-s">0x49]'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">le</span>
<span class="tok-w">          </span><span class="tok-s">'[0x4d,</span><span class="tok-nv"> </span><span class="tok-s">0x4d]'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">be</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">version</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2</span>
<span class="tok-w">      </span><span class="tok-c1"># ...</span>
<span class="tok-w">    </span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">ifd</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-c1"># inherits endianness of `tiff_body`</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="28410720" _msthash="759">In this example,  and all other numeric types without forced
endianness would use endianness determined by a switch expression in
 of . Moreover, this determined endianness
would also be propagated to other subtypes, declared within
.</font><code>version</code><code>meta/endian</code><code>tiff_body</code><code>tiff_body</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="22539036" _msthash="760">If  is neither  nor , i.e. both  fail,
this example would trigger a parsing exception. If you want to handle
it in a manner like "II means little-endian and everything else means
big-endian", use the normal else case ():</font><code>indicator</code><code>II</code><code>MM</code><code>cases</code><code>_</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">meta</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">endian</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">switch-on</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_root.indicator</span>
<span class="tok-w">    </span><span class="tok-nt">cases</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-s">'[0x49,</span><span class="tok-nv"> </span><span class="tok-s">0x49]'</span><span class="tok-p tok-p-Indicator">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">le</span>
<span class="tok-w">      </span><span class="tok-nt">_</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">be</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="param-types" _msttexthash="427492" _msthash="761">7.10. Parametric types</h3>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="7057479" _msthash="762">重要</div>
</td>
<td class="content" _msttexthash="39918437" _msthash="763">从 v0.8 开始提供的功能。</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="173751006" _msthash="764">请考虑以下格式，该格式包含两个类似的键值对列表：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">short_pairs</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">kv_pair_3</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x100</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">long_pairs</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">kv_pair_8</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x100</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">kv_pair_3</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">key</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">3</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">value</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">  </span><span class="tok-nt">kv_pair_8</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">key</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">8</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">value</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2352641889" _msthash="765">和 类型之间的唯一区别是
的长度。“短”对使用 3 字节长密钥，“长”对使用
使用 8 字节密钥。这是很多重复，想象一下
如果您需要 4 字节密钥或 6 字节密钥，则会发生这种情况。缓解
也就是说，可以声明一个所谓的“参数化”类型，比如这个：</font><code>kv_pair_3</code><code>kv_pair_8</code><code>key</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">kv_pair</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">params</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_key</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u2</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">key</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_key</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">str</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">value</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>params</code><font _mstmutation="1" _msttexthash="504298340" _msthash="766">行为类似于 ，但不是读取属性值
从流中，这些属性应作为
参数。这是通过指定
类型名称后括号中的参数值：</font><code>seq</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">short_pairs</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">kv_pair(3)</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x100</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">long_pairs</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">kv_pair(8)</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0x100</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="418663544" _msthash="767">当然，可以有多个参数（在这种情况下，它们
是逗号分隔的），并且可以使用多种类型：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">my_number</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">fancy_encrypted_number_format(3, true, [0x03, 0xb7, 0x8f])</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1837946448" _msthash="768">定义中的规范与
或 中的正常规格。它指定了一个纯
“类型”的概念，用于在编程中表示数据
语言，没有任何序列化细节（如字节序、大小、
转换、编码等）。因此，不能使用任何额外的键来
指定，但可以使用：</font><code>type</code><code>params</code><code>type</code><code>seq</code><code>instances</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="46768124" _msthash="769">没有类型或指定字节数组</font><code>bytes</code></p>
</li>
<li>
<p><code>str</code><font _mstmutation="1" _msttexthash="14442506" _msthash="770">指定字符串</font></p>
</li>
<li>
<p><code>bool</code><font _mstmutation="1" _msttexthash="13563160" _msthash="771">指定布尔值</font></p>
</li>
<li>
<p><code>struct</code><font _mstmutation="1" _msttexthash="79179737" _msthash="772">允许任意与 KaitaiStruct 兼容的用户类型</font></p>
</li>
<li>
<p><code>io</code><font _mstmutation="1" _msttexthash="29075553" _msthash="773">指定兼容 KaitaiStream 的 IO 流</font></p>
</li>
<li>
<p><code>any</code><font _mstmutation="1" _msttexthash="100700821" _msthash="774">允许任何类型（如果目标语言支持）</font></p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="5121168" _msthash="775">注意</div>
</td>
<td class="content"><font _mstmutation="1" _msttexthash="311133875" _msthash="776">无法从
文件（因为它们显然需要从
某处），因此典型的 Helper 方法不是
可供他们使用。</font><code>fromFile(…​)</code></td>
</tr>
</tbody></table>
</div>
</div>
<div class="sect2">
<h3 id="repeat-index" _msttexthash="19381505" _msthash="777">7.11. 重复指数</h3>
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<div class="title" _msttexthash="7057479" _msthash="778">重要</div>
</td>
<td class="content" _msttexthash="39918437" _msthash="779">从 v0.8 开始提供的功能。</td>
</tr>
</tbody></table>
</div>
<div class="paragraph">
<p _msttexthash="1277340038" _msthash="780">对于大多数格式，不需要访问循环迭代
指数。如果您有一个典型的存档文件目录，其中列出了文件
名称、文件正文的偏移量和文件正文的大小一起，只需
使用面向对象的方法：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_entry</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_entry</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_body</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_body</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">body</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_body</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_body</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="683975292" _msthash="781">但是，如果您的格式有一些信息布局稀疏，即
单独的文件大小表及其内容，可用于访问重复索引并解析大小数组中的大小：</font><code>_index</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">files</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_files[_index]</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="5167548217" _msthash="782">如果格式指定了文件<strong _mstmutation="1" _istranslated="1">偏移量</strong>，并且您想要读取
这些偏移量上存在的文件内容，事情变成了
更复杂。你不能在一个机构中读取所有的身体
具有重复的实例，因为用于重复属性
充当偏移量，从中开始按顺序读取所有项目
（有关更多信息，请参阅<a href="https://doc.kaitai.io/user_guide.html#keys-repeated" _mstmutation="1" _istranslated="1">与整个数组和重复属性中的每个元素相关的键</a>）。所以我们必须包装文件
body 在一个额外的用户类型中，我们可以在其中做实际的
解析。</font><code>pos</code><code>file_body</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="476408920" _msthash="783">但是，是一个“局部变量”，因此我们无法访问它
一旦我们进入子类型.解决方案是
传入使用<a href="https://doc.kaitai.io/user_guide.html#param-types" _mstmutation="1" _istranslated="1">参数类型</a>：</font><code>_index</code><code>file_body</code><code>_index</code><code>file_body</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-c1"># ... some other data here, might be variable size</span>
<span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_names</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-c1"># ... some other data here, might be variable size</span>
<span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">len_files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-c1"># ... some other data here, might be variable size</span>
<span class="tok-w">  </span><span class="tok-c1"># ...</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_bodies</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_body(_index)</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= pass `_index` into file_body</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_files</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_body</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">params</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">i</span><span class="tok-w">               </span><span class="tok-c1"># =&gt; receive `_index` as `i` here</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">s4</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">body</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_parent.ofs_files[i]</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_parent.len_files[i]</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="285944828" _msthash="784">一个更极端的例子是仅指定起始偏移量的格式，
但不直接指定文件的大小：</p>
</div>
<div class="literalblock">
<div class="content">
<pre>30 00 00 00│70 00 00 00│f0 02 00 00
           │           │
0x30       │0x70       │0x2f0
  └────────────┘└─────────────┘
    file 0        file 1

    start 0x30    start 0x70
    end   0x70    end   0x2f0
    ──────────    ───────────
    size  0x40    size  0x280</pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="28604615" _msthash="785">In this example, we have N = 3 offsets, which specify N - 1 = 2
sections. Sizes of the sections must be derived as the start of the
following section minus the start of the current section. To do such
a calculation, we can use  in the expressions:</font><code>_index</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_offsets</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-c1"># Just read offsets normally</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_files</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_offsets</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_bodies</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_body(_index)</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_offsets - 1</span>
<span class="tok-nt">type</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_body</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">params</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">i</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">s4</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">body</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_parent.ofs_files[i]</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_parent.ofs_files[i + 1] - _parent.ofs_files[i]</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="7591246" _msthash="786">In an even more complicated example, we have file names interleaved with
offsets. There are N - 1 file names and N offsets:</p>
</div>
<div class="literalblock">
<div class="content">
<pre>03 00 00 00       = 3 offsets, 2 files
30 00 00 00       = offset 0x30
66 6f 6f 2e 63 00 = "foo.c", null-terminated string
70 00 00 00       = offset 0x70
62 61 72 2e 63 00 = "bar.c", null-terminated string
f0 02 00 00       = offset 0x2f0</pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="16879993" _msthash="787">In this case we’ll need to do a calculation inside .
Once we pass the  from the parent type to it, it’s easy:</font><code>file_entry</code><code>_index</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_offsets</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">first_offset</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">files</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">file_entry(_index)</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= pass `_index` into file_entry</span>
<span class="tok-w">    </span><span class="tok-nt">repeat</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">expr</span>
<span class="tok-w">    </span><span class="tok-nt">repeat-expr</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">num_offsets - 1</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">file_entry</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">params</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">i</span><span class="tok-w">                </span><span class="tok-c1"># =&gt; receive `_index` as `i` here</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">name</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span>
<span class="tok-w">      </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_end</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u4</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">ofs_start</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-c1"># Normally we access previous file's end offset and use it as</span>
<span class="tok-w">        </span><span class="tok-c1"># our current start offset, but for the very first file we'll</span>
<span class="tok-w">        </span><span class="tok-c1"># use special field, as "previous file" does not exist for it.</span>
<span class="tok-w">        </span><span class="tok-nt">value</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-s">'i</span><span class="tok-nv"> </span><span class="tok-s">&gt;</span><span class="tok-nv"> </span><span class="tok-s">0</span><span class="tok-nv"> </span><span class="tok-s">?</span><span class="tok-nv"> </span><span class="tok-s">_parent.files[i</span><span class="tok-nv"> </span><span class="tok-s">-</span><span class="tok-nv"> </span><span class="tok-s">1].ofs_end</span><span class="tok-nv"> </span><span class="tok-s">:</span><span class="tok-nv"> </span><span class="tok-s">_parent.first_offset'</span>
<span class="tok-w">      </span><span class="tok-nt">body</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_start</span>
<span class="tok-w">        </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">ofs_end - ofs_start</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_common_pitfalls" _msttexthash="18922631" _msthash="788">8. 常见陷阱</h2>
<div class="sectionbody">
<div class="paragraph">
<p _msttexthash="54185989" _msthash="789">本节说明了
初学者 Kaitai Struct 用户。</p>
</div>
<div class="sect2">
<h3 id="_specifying_size_creates_a_substream" _msttexthash="52473642" _msthash="790">8.1. 指定大小会创建一个子流</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1081626325" _msthash="791">指定 （或 或 ） 时指定
用户类型创建子流。这意味着该用户类型中的所有偏移量 （） 相对于该子流的偏移量 （1）
开始，（2）限制在该子流中。例如：</font><code>size</code><code>size-eos</code><code>terminator</code><code>pos:
XXX</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">header</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">4</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">4</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= important size designation, creates a substream</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">byte_3</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">3</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span>
<span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">block</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">byte_3</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">3</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="21741746" _msthash="792">给定输入：</font><code>00 01 02 03|04 05 06 07</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><font _mstmutation="1" _msttexthash="229269872" _msthash="793">如果存在，则主类型将为 ，并且将是（由于其在子流中的分配）</font><code>size</code><code>byte_3</code><code>03</code><code>block.byte_3</code><code>07</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="233584936" _msthash="794">如果不存在，则主类型将是 ，并且也将是（因为它将重用根流）</font><code>size</code><code>byte_3</code><code>03</code><code>block.byte_3</code><code>03</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p _msttexthash="102843767" _msthash="795">避免这个陷阱很简单：有两种方法：</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><font _mstmutation="1" _msttexthash="135942183" _msthash="796">避免在不需要子流时创建子流（即删除指定）</font><code>size</code></p>
</li>
<li>
<p><font _mstmutation="1" _msttexthash="103530349" _msthash="797">在解析实例中强制使用特定流，例如：</font><code>io: XXX</code></p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">types</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">block</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">      </span><span class="tok-nt">byte_3</span><span class="tok-p">:</span>
<span class="tok-w">        </span><span class="tok-nt">io</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">_root._io</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= thanks to this, always points to a byte in main stream</span>
<span class="tok-w">        </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">3</span>
<span class="tok-w">        </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">u1</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_not_specifying_size_does_not_create_a_substream" _msttexthash="53734096" _msthash="798">8.2. 未指定大小不会创建子流</h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1449933303" _msthash="799">与前一个陷阱相反，没有指定（或 或 ）
不会创建子流，因此访问该元素的 IO 将
有效地指向主流（因此将是一个无操作）。在这个
例如，这个想法是用两个不同的区域重新分析两次
类型和：</font><code>size</code><code>size-eos</code><code>terminator</code><code>block</code><code>type1</code><code>type2</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">header</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">strz</span><span class="tok-w"> </span><span class="tok-c1"># some variable-sized field before `block`</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_as_type1</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">type1</span>
<span class="tok-w">    </span><span class="tok-nt">size</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">16</span><span class="tok-w"> </span><span class="tok-c1"># &lt;= important, creates a substream</span>
<span class="tok-nt">instances</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-nt">block_as_type2</span><span class="tok-p">:</span>
<span class="tok-w">    </span><span class="tok-nt">io</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">block_as_type1._io</span>
<span class="tok-w">    </span><span class="tok-nt">pos</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">0</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">type2</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="429921440" _msthash="800">如果缺少，将重用主
stream 并将解析一段数据，这很可能
是 的一部分，而不是 所占领的区域。</font><code>size</code><code>block_as_type2</code><code>pos: 0</code><code>header</code><code>block_as_type1</code></p>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="136752967" _msthash="801">为避免此陷阱，请始终确保在要创建子流时指定 / /。</font><code>size</code><code>size-eos</code><code>terminator</code></p>
</div>
</div>
<div class="sect2">
<h3 id="_applying_process_without_a_size"><font _mstmutation="1" _msttexthash="34989695" _msthash="802">8.3. 不带尺寸的申请</font><code>process</code></h3>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="803137426" _msthash="803">在所有情况下，必须定义要处理的数据的大小（带或带），即这是合法的（没有
过程 — 大小取将由 决定 ，读取
通常来自流）：</font><code>size: …​</code><code>size-eos: true</code><code>some_body_type</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">some_body_type</span></code></pre>
</div>
</div>
<div class="paragraph">
<p _msttexthash="16979482" _msthash="804">这不是：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="yaml"><span></span><span class="tok-nt">seq</span><span class="tok-p">:</span>
<span class="tok-w">  </span><span class="tok-p tok-p-Indicator">-</span><span class="tok-w"> </span><span class="tok-nt">id</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">body</span>
<span class="tok-w">    </span><span class="tok-nt">process</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">xor(0xaa)</span>
<span class="tok-w">    </span><span class="tok-nt">type</span><span class="tok-p">:</span><span class="tok-w"> </span><span class="tok-l tok-l-Scalar tok-l-Scalar-Plain">some_body_type</span>
<span class="tok-w">    </span><span class="tok-c1"># will not compile — lacks size</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="534406262" _msthash="805">这是因为大多数处理算法需要知道数据的大小
事先处理，最终大小可能是
仅在运行时确定，在进行解析后。</font><code>some_body_type</code></p>
</div>
</div>
<div class="sect2">
<h3 id="keys-repeated" _msttexthash="130987753" _msthash="806">8.4. 与整个数组和重复属性中每个元素相关的键</h3>
<div class="paragraph">
<p _msttexthash="501312097" _msthash="807">如果您在属性中使用重复，请务必了解
哪些 YAML 键引用整个数组，哪些键影响单个数组
元素。列表如下：</p>
</div>
<table class="tableblock frame-none grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><div class="content"><div class="ulist">
<div class="title" _msttexthash="11675443" _msthash="808">整个阵列</div>
<ul>
<li>
<p><code>doc</code></p>
</li>
<li>
<p><code>doc-ref</code></p>
</li>
<li>
<p><code>id</code></p>
</li>
<li>
<p><code>if</code></p>
</li>
<li>
<p><code>io</code></p>
</li>
<li>
<p><code>pos</code></p>
</li>
</ul>
</div></div></td>
<td class="tableblock halign-left valign-top"><div class="content"><div class="ulist">
<div class="title" _msttexthash="10620454" _msthash="809">单个元素</div>
<ul>
<li>
<p><code>size</code></p>
</li>
<li>
<p><code>size-eos</code></p>
</li>
<li>
<p><code>type</code></p>
</li>
<li>
<p><code>enum</code></p>
</li>
<li>
<p><code>contents</code></p>
</li>
<li>
<p><code>pad-right</code></p>
</li>
<li>
<p><code>terminator</code></p>
</li>
<li>
<p><code>include</code></p>
</li>
<li>
<p><code>consume</code></p>
</li>
<li>
<p><code>eos-error</code></p>
</li>
<li>
<p><code>encoding</code></p>
</li>
<li>
<p><code>process</code></p>
</li>
</ul>
</div></div></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p _msttexthash="880292361" _msthash="810">如果你需要一个组的某个密钥来“属于”另一个组，你
必须添加额外的用户定义类型。根据您的需要，
可能需要包装单个项目或整个项目
数组。</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p _msttexthash="663181454" _msthash="811">强制将与<strong _istranslated="1">单个元素</strong>相关的键应用于整体
数组改为：创建一个<strong _istranslated="1">包装整个数组</strong>的用户类型，
并将键应用于使用此包装类型的属性。</p>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="2577942744" _msthash="812">您可以在<a href="https://doc.kaitai.io/user_guide.html#repeat-until-size-limit" _mstmutation="1" _istranslated="1">重复直到总大小达到限制</a>中看到示例。我们知道
只是整个数组的，但在字段上指定的键
使用重复意味着每个项目的大小，因此有必要添加包含数组的类型。那么创建就没有问题了
总大小的子流，并将此类型放入其中，因为键和不再在同一个属性中相遇。</font><code>size</code><code>size</code><code>file_entries</code><code>size</code><code>repeat</code></p>
</div>
</li>
<li>
<p _msttexthash="834087449" _msthash="813">强制将与<strong _istranslated="1">整个数组</strong>相关的键应用于每个数组
单个项目改为：创建一个<strong _istranslated="1">包装单个元素</strong>的用户类型，
并将键应用于此包装器的属性和项类型本身。</p>
<div class="paragraph">
<p><font _mstmutation="1" _msttexthash="1802683194" _msthash="814">例如，<a href="https://doc.kaitai.io/user_guide.html#repeat-index" _mstmutation="1" _istranslated="1">重复索引</a>部分中的第二个示例显示了一个存档
文件目录具有分离的文件偏移量和大小，我们需要读取
实际文件正文。我们不想表示数组的偏移量，而是
项的偏移量，因此有必要将项包装在自己的类型中。</font><code>pos</code></p>
</div>
</li>
</ol>
</div>
</div>
</div>
</div>
</div>
    <div id="footer" _msttexthash="30816435" _msthash="815">© 2015–2024 开泰项目</div>
    <script src="./Kaitai Struct 用户指南_files/jquery-1.12.3.min.js.下载"></script>
    <script src="./Kaitai Struct 用户指南_files/bootstrap.min.js.下载"></script>

    <script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-76299550-1', 'auto');
        ga('send', 'pageview');
    </script>
<script src="./Kaitai Struct 用户指南_files/asciidoctor-tabs.js.下载"></script>

</body></html>